Use exception handling to implement the IsBad* functions.

Removed /proc/self/maps parsing as it is not very useful with .so libs.
This commit is contained in:
Alexandre Julliard 2000-05-01 21:23:02 +00:00
parent 8c21dfcf0f
commit 72eb8d39d4
2 changed files with 65 additions and 124 deletions

View file

@ -30,7 +30,6 @@ extern HGLOBAL16 GLOBAL_Alloc( WORD flags, DWORD size, HGLOBAL16 hOwner,
extern WORD WINAPI GlobalHandleToSel16( HGLOBAL16 handle );
/* memory/virtual.c */
extern BOOL VIRTUAL_Init( void );
extern DWORD VIRTUAL_GetPageSize(void);
extern DWORD VIRTUAL_GetGranularity(void);
extern LPVOID VIRTUAL_MapFileW( LPCWSTR name );

View file

@ -21,6 +21,7 @@
#include <sys/mman.h>
#endif
#include "winbase.h"
#include "wine/exception.h"
#include "winerror.h"
#include "file.h"
#include "process.h"
@ -42,7 +43,6 @@ typedef struct _FV
UINT base; /* Base address */
UINT size; /* Size in bytes */
UINT flags; /* Allocation flags */
UINT offset; /* Offset from start of mapped file */
HANDLE mapping; /* Handle to the file mapping */
HANDLERPROC handlerProc; /* Fault handler */
LPVOID handlerArg; /* Fault handler argument */
@ -81,12 +81,11 @@ static FILE_VIEW *VIRTUAL_FirstView;
/* These are always the same on an i386, and it will be faster this way */
# define page_mask 0xfff
# define page_shift 12
# define granularity_mask 0xffff
#else
static UINT page_shift;
static UINT page_mask;
static UINT granularity_mask; /* Allocation granularity (usually 64k) */
#endif /* __i386__ */
#define granularity_mask 0xffff /* Allocation granularity (usually 64k) */
#define ROUND_ADDR(addr) \
((UINT)(addr) & ~page_mask)
@ -97,6 +96,15 @@ static UINT granularity_mask; /* Allocation granularity (usually 64k) */
#define VIRTUAL_DEBUG_DUMP_VIEW(view) \
if (!TRACE_ON(virtual)); else VIRTUAL_DumpView(view)
/* filter for page-fault exceptions */
static WINE_EXCEPTION_FILTER(page_fault)
{
if (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION)
return EXCEPTION_EXECUTE_HANDLER;
return EXCEPTION_CONTINUE_SEARCH;
}
/***********************************************************************
* VIRTUAL_GetProtStr
*/
@ -127,7 +135,7 @@ static void VIRTUAL_DumpView( FILE_VIEW *view )
view->base, view->base + view->size - 1,
(view->flags & VFLAG_SYSTEM) ? " (system)" : "" );
if (view->mapping)
DPRINTF( " %d @ %08x\n", view->mapping, view->offset );
DPRINTF( " %d\n", view->mapping );
else
DPRINTF( " (anonymous)\n");
@ -206,7 +214,6 @@ static FILE_VIEW *VIRTUAL_CreateView( UINT base, UINT size, UINT offset,
view->base = base;
view->size = size << page_shift;
view->flags = flags;
view->offset = offset;
view->mapping = mapping;
view->protect = vprot;
view->handlerProc = NULL;
@ -385,39 +392,12 @@ static BOOL VIRTUAL_SetProt(
}
/***********************************************************************
* VIRTUAL_CheckFlags
*
* Check that all pages in a range have the given flags.
*
* RETURNS
* TRUE: They do
* FALSE: They do not
*/
static BOOL VIRTUAL_CheckFlags(
UINT base, /* [in] Starting address */
UINT size, /* [in] Size in bytes */
BYTE flags /* [in] Flags to check for */
) {
FILE_VIEW *view;
UINT page;
if (!size) return TRUE;
if (!(view = VIRTUAL_FindView( base ))) return FALSE;
if (view->base + view->size < base + size) return FALSE;
page = (base - view->base) >> page_shift;
size = ROUND_SIZE( base, size ) >> page_shift;
while (size--) if ((view->prot[page++] & flags) != flags) return FALSE;
return TRUE;
}
/***********************************************************************
* VIRTUAL_Init
*/
BOOL VIRTUAL_Init(void)
#ifndef page_mask
DECL_GLOBAL_CONSTRUCTOR(VIRTUAL_Init)
{
#ifndef __i386__
DWORD page_size;
# ifdef HAVE_GETPAGESIZE
@ -430,52 +410,12 @@ BOOL VIRTUAL_Init(void)
# endif
# endif
page_mask = page_size - 1;
granularity_mask = 0xffff; /* hard-coded for now */
/* Make sure we have a power of 2 */
assert( !(page_size & page_mask) );
page_shift = 0;
while ((1 << page_shift) != page_size) page_shift++;
#endif /* !__i386__ */
#ifdef linux
{
/* Do not use stdio here since it may temporarily change the size
* of some segments (ie libc6 adds 0x1000 per open FILE)
*/
int fd = open ("/proc/self/maps", O_RDONLY);
if (fd >= 0)
{
char buffer[512]; /* line might be rather long in 2.1 */
for (;;)
{
int start, end, offset;
char r, w, x, p;
BYTE vprot = VPROT_COMMITTED;
char * ptr = buffer;
int count = sizeof(buffer);
while (1 == read(fd, ptr, 1) && *ptr != '\n' && --count > 0)
ptr++;
if (*ptr != '\n') break;
*ptr = '\0';
sscanf( buffer, "%x-%x %c%c%c%c %x",
&start, &end, &r, &w, &x, &p, &offset );
if (r == 'r') vprot |= VPROT_READ;
if (w == 'w') vprot |= VPROT_WRITE;
if (x == 'x') vprot |= VPROT_EXEC;
if (p == 'p') vprot |= VPROT_WRITECOPY;
VIRTUAL_CreateView( start, end - start, 0,
VFLAG_SYSTEM, vprot, -1 );
}
close (fd);
}
}
#endif /* linux */
return TRUE;
}
#endif /* page_mask */
/***********************************************************************
@ -943,10 +883,24 @@ DWORD WINAPI VirtualQueryEx(
*/
BOOL WINAPI IsBadReadPtr(
LPCVOID ptr, /* Address of memory block */
UINT size /* Size of block */
) {
return !VIRTUAL_CheckFlags( (UINT)ptr, size,
VPROT_READ | VPROT_COMMITTED );
UINT size ) /* Size of block */
{
__TRY
{
volatile const char *p = ptr;
volatile const char *end = p + size - 1;
char dummy;
while (p < end)
{
dummy = *p;
p += page_mask + 1;
}
dummy = *end;
}
__EXCEPT(page_fault) { return TRUE; }
__ENDTRY
return FALSE;
}
@ -959,10 +913,23 @@ BOOL WINAPI IsBadReadPtr(
*/
BOOL WINAPI IsBadWritePtr(
LPVOID ptr, /* [in] Address of memory block */
UINT size /* [in] Size of block in bytes */
) {
return !VIRTUAL_CheckFlags( (UINT)ptr, size,
VPROT_WRITE | VPROT_COMMITTED );
UINT size ) /* [in] Size of block in bytes */
{
__TRY
{
volatile char *p = ptr;
volatile char *end = p + size - 1;
while (p < end)
{
*p |= 0;
p += page_mask + 1;
}
*end |= 0;
}
__EXCEPT(page_fault) { return TRUE; }
__ENDTRY
return FALSE;
}
@ -1001,10 +968,9 @@ BOOL WINAPI IsBadHugeWritePtr(
* FALSE: Process has read access to specified memory
* TRUE: Otherwise
*/
BOOL WINAPI IsBadCodePtr(
FARPROC ptr /* [in] Address of function */
) {
return !VIRTUAL_CheckFlags( (UINT)ptr, 1, VPROT_EXEC | VPROT_COMMITTED );
BOOL WINAPI IsBadCodePtr( FARPROC ptr ) /* [in] Address of function */
{
return IsBadReadPtr( ptr, 1 );
}
@ -1017,27 +983,15 @@ BOOL WINAPI IsBadCodePtr(
*/
BOOL WINAPI IsBadStringPtrA(
LPCSTR str, /* [in] Address of string */
UINT max /* [in] Maximum size of string */
) {
FILE_VIEW *view;
UINT page, count;
if (!max) return FALSE;
if (!(view = VIRTUAL_FindView( (UINT)str ))) return TRUE;
page = ((UINT)str - view->base) >> page_shift;
count = page_mask + 1 - ((UINT)str & page_mask);
while (max)
UINT max ) /* [in] Maximum size of string */
{
__TRY
{
if ((view->prot[page] & (VPROT_READ | VPROT_COMMITTED)) !=
(VPROT_READ | VPROT_COMMITTED))
return TRUE;
if (count > max) count = max;
max -= count;
while (count--) if (!*str++) return FALSE;
if (++page >= view->size >> page_shift) return TRUE;
count = page_mask + 1;
volatile const char *p = str;
while (p < str + max) if (!*p++) break;
}
__EXCEPT(page_fault) { return TRUE; }
__ENDTRY
return FALSE;
}
@ -1048,25 +1002,13 @@ BOOL WINAPI IsBadStringPtrA(
*/
BOOL WINAPI IsBadStringPtrW( LPCWSTR str, UINT max )
{
FILE_VIEW *view;
UINT page, count;
if (!max) return FALSE;
if (!(view = VIRTUAL_FindView( (UINT)str ))) return TRUE;
page = ((UINT)str - view->base) >> page_shift;
count = (page_mask + 1 - ((UINT)str & page_mask)) / sizeof(WCHAR);
while (max)
__TRY
{
if ((view->prot[page] & (VPROT_READ | VPROT_COMMITTED)) !=
(VPROT_READ | VPROT_COMMITTED))
return TRUE;
if (count > max) count = max;
max -= count;
while (count--) if (!*str++) return FALSE;
if (++page >= view->size >> page_shift) return TRUE;
count = (page_mask + 1) / sizeof(WCHAR);
volatile const WCHAR *p = str;
while (p < str + max) if (!*p++) break;
}
__EXCEPT(page_fault) { return TRUE; }
__ENDTRY
return FALSE;
}