/*
 * Debugger memory handling
 *
 * Copyright 1993 Eric Youngdale
 * Copyright 1995 Alexandre Julliard
 */

#include <stdio.h>
#include <stdlib.h>
#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, FALSE );
        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, TRUE );
                    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<count; i++) 
		{
                    if (!DBG_CHECK_READ_PTR( &addr, sizeof(int) )) return;
                    fprintf(stderr," %8.8x", *dump++);
                    addr.off += sizeof(int);
                    if ((i % 8) == 7)
                    {
                        fprintf(stderr,"\n");
                        DEBUG_PrintAddress( &addr, dbg_mode, FALSE );
                        fprintf(stderr,": ");
                    }
		}
		fprintf(stderr,"\n");
		return;
	
	case 'd':
		dump = (unsigned int *)pnt;
		for(i=0; i<count; i++) 
		{
                    if (!DBG_CHECK_READ_PTR( &addr, sizeof(int) )) return;
                    fprintf(stderr," %d", *dump++);
                    addr.off += sizeof(int);
                    if ((i % 8) == 7)
                    {
                        fprintf(stderr,"\n");
                        DEBUG_PrintAddress( &addr, dbg_mode, FALSE );
                        fprintf(stderr,": ");
                    }
		}
		fprintf(stderr,"\n");
		return;
	
	case 'w':
		wdump = (unsigned short *)pnt;
		for(i=0; i<count; i++) 
		{
                    if (!DBG_CHECK_READ_PTR( &addr, sizeof(short) )) return;
                    fprintf(stderr," %04x", *wdump++);
                    addr.off += sizeof(short);
                    if ((i % 8) == 7)
                    {
                        fprintf(stderr,"\n");
                        DEBUG_PrintAddress( &addr, dbg_mode, FALSE );
                        fprintf(stderr,": ");
                    }
		}
		fprintf(stderr,"\n");
		return;
	
	case 'c':
		for(i=0; i<count; i++) 
		{
                    if (!DBG_CHECK_READ_PTR( &addr, sizeof(char) )) return;
                    if(*pnt < 0x20)
                    {
                        fprintf(stderr,"  ");
                        pnt++;
                    }
                    else fprintf(stderr," %c", *pnt++);
                    addr.off++;
                    if ((i % 32) == 31)
                    {
                        fprintf(stderr,"\n");
                        DEBUG_PrintAddress( &addr, dbg_mode, FALSE );
                        fprintf(stderr,": ");
                    }
		}
		fprintf(stderr,"\n");
		return;
	
	case 'b':
		for(i=0; i<count; i++) 
		{
                    if (!DBG_CHECK_READ_PTR( &addr, sizeof(char) )) return;
                    fprintf(stderr," %02x", (*pnt++) & 0xff);
                    addr.off++;
                    if ((i % 16) == 15)
                    {
                        fprintf(stderr,"\n");
                        DEBUG_PrintAddress( &addr, dbg_mode, FALSE );
                        fprintf(stderr,": ");
                    }
		}
		fprintf(stderr,"\n");
		return;
	}
}
