Alexandre Julliard : ntdll: Add a helper function for setting bits in page protection bytes.

Alexandre Julliard julliard at winehq.org
Tue Sep 5 15:18:50 CDT 2017


Module: wine
Branch: master
Commit: e4b5e5da8ad0adc0cbb60b8937bc4406a21ae38d
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=e4b5e5da8ad0adc0cbb60b8937bc4406a21ae38d

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Tue Sep  5 14:18:06 2017 +0200

ntdll: Add a helper function for setting bits in page protection bytes.

Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 dlls/ntdll/virtual.c | 63 ++++++++++++++++++++++++++++++----------------------
 1 file changed, 36 insertions(+), 27 deletions(-)

diff --git a/dlls/ntdll/virtual.c b/dlls/ntdll/virtual.c
index d681b4c..d34fbed 100644
--- a/dlls/ntdll/virtual.c
+++ b/dlls/ntdll/virtual.c
@@ -177,6 +177,21 @@ static void set_page_vprot( struct file_view *view, const void *addr, size_t siz
 
 
 /***********************************************************************
+ *           set_page_vprot_bits
+ *
+ * Set or clear bits in a range of page protection bytes.
+ */
+static void set_page_vprot_bits( struct file_view *view, const void *addr, size_t size,
+                                 BYTE set, BYTE clear )
+{
+    BYTE *ptr = view->prot + (((const char *)addr - (const char *)view->base) >> page_shift);
+    size_t i;
+
+    for (i = 0; i < ROUND_SIZE( addr, size ) >> page_shift; i++) ptr[i] = (ptr[i] & ~clear) | set;
+}
+
+
+/***********************************************************************
  *           VIRTUAL_GetProtStr
  */
 static const char *VIRTUAL_GetProtStr( BYTE prot )
@@ -717,14 +732,12 @@ static BOOL VIRTUAL_SetProt( struct file_view *view, /* [in] Pointer to view */
         UINT i, count;
         char *addr = base;
         int prot;
-        BYTE *p = view->prot + ((addr - (char *)view->base) >> page_shift);
 
-        p[0] = vprot | (p[0] & VPROT_WRITEWATCH);
-        unix_prot = VIRTUAL_GetUnixProt( p[0] );
+        set_page_vprot_bits( view, base, size, vprot & ~VPROT_WRITEWATCH, ~vprot & ~VPROT_WRITEWATCH );
+        unix_prot = VIRTUAL_GetUnixProt( get_page_vprot( view, addr ));
         for (count = i = 1; i < size >> page_shift; i++, count++)
         {
-            p[i] = vprot | (p[i] & VPROT_WRITEWATCH);
-            prot = VIRTUAL_GetUnixProt( p[i] );
+            prot = VIRTUAL_GetUnixProt( get_page_vprot( view, addr + (count << page_shift) ));
             if (prot == unix_prot) continue;
             mprotect_exec( addr, count << page_shift, unix_prot, view->protect );
             addr += count << page_shift;
@@ -767,14 +780,12 @@ static void reset_write_watches( struct file_view *view, void *base, SIZE_T size
     SIZE_T i, count;
     int prot, unix_prot;
     char *addr = base;
-    BYTE *p = view->prot + ((addr - (char *)view->base) >> page_shift);
 
-    p[0] |= VPROT_WRITEWATCH;
-    unix_prot = VIRTUAL_GetUnixProt( p[0] );
+    set_page_vprot_bits( view, base, size, VPROT_WRITEWATCH, 0 );
+    unix_prot = VIRTUAL_GetUnixProt( get_page_vprot( view, addr ));
     for (count = i = 1; i < size >> page_shift; i++, count++)
     {
-        p[i] |= VPROT_WRITEWATCH;
-        prot = VIRTUAL_GetUnixProt( p[i] );
+        prot = VIRTUAL_GetUnixProt( get_page_vprot( view, addr + (count << page_shift) ));
         if (prot == unix_prot) continue;
         mprotect_exec( addr, count << page_shift, unix_prot, view->protect );
         addr += count << page_shift;
@@ -1051,7 +1062,7 @@ static SIZE_T get_committed_size( struct file_view *view, void *base, BYTE *vpro
                 if (reply->committed)
                 {
                     *vprot |= VPROT_COMMITTED;
-                    for (i = 0; i < ret >> page_shift; i++) view->prot[start+i] |= VPROT_COMMITTED;
+                    set_page_vprot_bits( view, base, ret, VPROT_COMMITTED, 0 );
                 }
             }
         }
@@ -1074,9 +1085,7 @@ static NTSTATUS decommit_pages( struct file_view *view, size_t start, size_t siz
 {
     if (wine_anon_mmap( (char *)view->base + start, size, PROT_NONE, MAP_FIXED ) != (void *)-1)
     {
-        BYTE *p = view->prot + (start >> page_shift);
-        size >>= page_shift;
-        while (size--) *p++ &= ~VPROT_COMMITTED;
+        set_page_vprot_bits( view, (char *)view->base + start, size, 0, VPROT_COMMITTED );
         return STATUS_SUCCESS;
     }
     return FILE_GetNtStatus();
@@ -1610,20 +1619,20 @@ NTSTATUS virtual_handle_fault( LPCVOID addr, DWORD err, BOOL on_signal_stack )
     if ((view = VIRTUAL_FindView( addr, 0 )))
     {
         void *page = ROUND_ADDR( addr, page_mask );
-        BYTE *vprot = &view->prot[((const char *)page - (const char *)view->base) >> page_shift];
+        BYTE vprot = get_page_vprot( view, page );
         if ((err & EXCEPTION_WRITE_FAULT) && (view->protect & VPROT_WRITEWATCH))
         {
-            if (*vprot & VPROT_WRITEWATCH)
+            if (vprot & VPROT_WRITEWATCH)
             {
-                *vprot &= ~VPROT_WRITEWATCH;
-                VIRTUAL_SetProt( view, page, page_size, *vprot );
+                set_page_vprot_bits( view, page, page_size, 0, VPROT_WRITEWATCH );
+                VIRTUAL_SetProt( view, page, page_size, get_page_vprot( view, page ));
             }
             /* ignore fault if page is writable now */
-            if (VIRTUAL_GetUnixProt( *vprot ) & PROT_WRITE) ret = STATUS_SUCCESS;
+            if (VIRTUAL_GetUnixProt( get_page_vprot( view, page )) & PROT_WRITE) ret = STATUS_SUCCESS;
         }
-        if (!on_signal_stack && (*vprot & VPROT_GUARD))
+        if (!on_signal_stack && (vprot & VPROT_GUARD))
         {
-            VIRTUAL_SetProt( view, page, page_size, *vprot & ~VPROT_GUARD );
+            VIRTUAL_SetProt( view, page, page_size, vprot & ~VPROT_GUARD );
             ret = STATUS_GUARD_PAGE_VIOLATION;
         }
     }
@@ -1812,24 +1821,24 @@ SIZE_T virtual_uninterrupted_write_memory( void *addr, const void *buffer, SIZE_
             while (bytes_written < size)
             {
                 void *page = ROUND_ADDR( addr, page_mask );
-                BYTE *p = view->prot + (((const char *)page - (const char *)view->base) >> page_shift);
+                BYTE vprot = get_page_vprot( view, page );
                 SIZE_T block_size;
 
                 /* If the page is not writable then check for write watches
                  * before giving up. This can be done without raising a real
                  * exception. Similar to virtual_handle_fault. */
-                if (!(VIRTUAL_GetUnixProt( *p ) & PROT_WRITE))
+                if (!(VIRTUAL_GetUnixProt( vprot ) & PROT_WRITE))
                 {
                     if (!(view->protect & VPROT_WRITEWATCH))
                         break;
 
-                    if (*p & VPROT_WRITEWATCH)
+                    if (vprot & VPROT_WRITEWATCH)
                     {
-                        *p &= ~VPROT_WRITEWATCH;
-                        VIRTUAL_SetProt( view, page, page_size, *p );
+                        set_page_vprot_bits( view, page, page_size, 0, VPROT_WRITEWATCH );
+                        VIRTUAL_SetProt( view, page, page_size, get_page_vprot( view, page ));
                     }
                     /* ignore fault if page is writable now */
-                    if (!(VIRTUAL_GetUnixProt( *p ) & PROT_WRITE))
+                    if (!(VIRTUAL_GetUnixProt( get_page_vprot( view, page )) & PROT_WRITE))
                         break;
                 }
 




More information about the wine-cvs mailing list