From 35614462443c100b6753b335b58a134fed4b5c35 Mon Sep 17 00:00:00 2001
From: Ulf Hermann <ulf.hermann@qt.io>
Date: Wed, 16 Dec 2020 16:45:36 +0100
Subject: [PATCH 23/28] JIT: When making memory writable, include the exception
 handler

makeWritable() rounds the memory down to the next page boundary. Usually
we include the exception handler this way, unless the offset from the
page boundary is less than the exception handler size. Make it explicit
that we do want the exception handler to be writable, too.

Fixes: QTBUG-89513
Change-Id: I2fb8fb0e1dcc3450b036924463dc1b40d2020c46
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
(cherry picked from commit 86a595b126bc6794380dc00af80ec4802f7d058c)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
---
 src/3rdparty/masm/assembler/AssemblerBuffer.h      |  4 ++--
 src/3rdparty/masm/assembler/LinkBuffer.h           |  9 +++++----
 .../masm/assembler/MacroAssemblerCodeRef.h         |  6 +++---
 src/3rdparty/masm/stubs/ExecutableAllocator.h      | 11 ++++++++---
 src/qml/jsruntime/qv4executableallocator.cpp       | 14 ++++++++++++--
 src/qml/jsruntime/qv4executableallocator_p.h       | 10 ++++++++--
 src/qml/jsruntime/qv4functiontable_win64.cpp       |  4 ++--
 7 files changed, 40 insertions(+), 18 deletions(-)

diff --git a/src/3rdparty/masm/assembler/AssemblerBuffer.h b/src/3rdparty/masm/assembler/AssemblerBuffer.h
index 45874235b6..2292a4c244 100644
--- a/src/3rdparty/masm/assembler/AssemblerBuffer.h
+++ b/src/3rdparty/masm/assembler/AssemblerBuffer.h
@@ -140,9 +140,9 @@ namespace JSC {
             if (!result)
                 return 0;
 
-            ExecutableAllocator::makeWritable(result->start(), result->sizeInBytes());
+            ExecutableAllocator::makeWritable(result->memoryStart(), result->memorySize());
 
-            memcpy(result->start(), m_buffer, m_index);
+            memcpy(result->codeStart(), m_buffer, m_index);
             
             return result.release();
         }
diff --git a/src/3rdparty/masm/assembler/LinkBuffer.h b/src/3rdparty/masm/assembler/LinkBuffer.h
index ba57564a1d..fa669deaf9 100644
--- a/src/3rdparty/masm/assembler/LinkBuffer.h
+++ b/src/3rdparty/masm/assembler/LinkBuffer.h
@@ -333,7 +333,7 @@ inline void LinkBufferBase<MacroAssembler, ExecutableOffsetCalculator>::linkCode
     m_executableMemory = m_assembler->m_assembler.executableCopy(*m_globalData, ownerUID, effort);
     if (!m_executableMemory)
         return;
-    m_code = m_executableMemory->start();
+    m_code = m_executableMemory->codeStart();
     m_size = m_assembler->m_assembler.codeSize();
     ASSERT(m_code);
 }
@@ -355,7 +355,8 @@ void LinkBufferBase<MacroAssembler, ExecutableOffsetCalculator>::performFinaliza
 template <typename MacroAssembler, template <typename T> class ExecutableOffsetCalculator>
 inline void LinkBufferBase<MacroAssembler, ExecutableOffsetCalculator>::makeExecutable()
 {
-    ExecutableAllocator::makeExecutable(code(), static_cast<int>(m_size));
+    ExecutableAllocator::makeExecutable(m_executableMemory->memoryStart(),
+                                        m_executableMemory->memorySize());
 }
 
 template <typename MacroAssembler>
@@ -442,9 +443,9 @@ inline void BranchCompactingLinkBuffer<MacroAssembler>::linkCode(void* ownerUID,
     m_executableMemory = m_globalData->executableAllocator.allocate(*m_globalData, m_initialSize, ownerUID, effort);
     if (!m_executableMemory)
         return;
-    m_code = (uint8_t*)m_executableMemory->start();
+    m_code = (uint8_t*)m_executableMemory->codeStart();
     ASSERT(m_code);
-    ExecutableAllocator::makeWritable(m_code, m_initialSize);
+    ExecutableAllocator::makeWritable(m_executableMemory->memoryStart(), m_executableMemory->memorySize());
     uint8_t* inData = (uint8_t*)m_assembler->unlinkedCode();
     uint8_t* outData = reinterpret_cast<uint8_t*>(m_code);
     int readPtr = 0;
diff --git a/src/3rdparty/masm/assembler/MacroAssemblerCodeRef.h b/src/3rdparty/masm/assembler/MacroAssemblerCodeRef.h
index a7e78ad78f..cde9751108 100644
--- a/src/3rdparty/masm/assembler/MacroAssemblerCodeRef.h
+++ b/src/3rdparty/masm/assembler/MacroAssemblerCodeRef.h
@@ -357,11 +357,11 @@ public:
     }
 
     MacroAssemblerCodeRef(PassRefPtr<ExecutableMemoryHandle> executableMemory)
-        : m_codePtr(executableMemory->start())
+        : m_codePtr(executableMemory->codeStart())
         , m_executableMemory(executableMemory)
     {
         ASSERT(m_executableMemory->isManaged());
-        ASSERT(m_executableMemory->start());
+        ASSERT(m_executableMemory->codeStart());
         ASSERT(m_codePtr);
     }
     
@@ -395,7 +395,7 @@ public:
     {
         if (!m_executableMemory)
             return 0;
-        return m_executableMemory->sizeInBytes();
+        return m_executableMemory->codeSize();
     }
     
     bool tryToDisassemble(const char* prefix) const
diff --git a/src/3rdparty/masm/stubs/ExecutableAllocator.h b/src/3rdparty/masm/stubs/ExecutableAllocator.h
index a439c53827..f984704023 100644
--- a/src/3rdparty/masm/stubs/ExecutableAllocator.h
+++ b/src/3rdparty/masm/stubs/ExecutableAllocator.h
@@ -82,9 +82,14 @@ struct ExecutableMemoryHandle : public RefCounted<ExecutableMemoryHandle> {
 
     inline bool isManaged() const { return true; }
 
-    void *exceptionHandler() { return m_allocation->exceptionHandler(); }
-    void *start() { return m_allocation->start(); }
-    size_t sizeInBytes() { return m_size; }
+    void *memoryStart() { return m_allocation->memoryStart(); }
+    size_t memorySize() { return m_allocation->memorySize(); }
+
+    void *exceptionHandlerStart() { return m_allocation->exceptionHandlerStart(); }
+    size_t exceptionHandlerSize() { return m_allocation->exceptionHandlerSize(); }
+
+    void *codeStart() { return m_allocation->codeStart(); }
+    size_t codeSize() { return m_size; }
 
     QV4::ExecutableAllocator::ChunkOfPages *chunk() const
     { return m_allocator->chunkForAllocation(m_allocation); }
diff --git a/src/qml/jsruntime/qv4executableallocator.cpp b/src/qml/jsruntime/qv4executableallocator.cpp
index 7ee6f39aa2..c06773d3c5 100644
--- a/src/qml/jsruntime/qv4executableallocator.cpp
+++ b/src/qml/jsruntime/qv4executableallocator.cpp
@@ -45,12 +45,22 @@
 
 using namespace QV4;
 
-void *ExecutableAllocator::Allocation::exceptionHandler() const
+void *ExecutableAllocator::Allocation::exceptionHandlerStart() const
 {
     return reinterpret_cast<void*>(addr);
 }
 
-void *ExecutableAllocator::Allocation::start() const
+size_t ExecutableAllocator::Allocation::exceptionHandlerSize() const
+{
+    return QV4::exceptionHandlerSize();
+}
+
+void *ExecutableAllocator::Allocation::memoryStart() const
+{
+    return reinterpret_cast<void*>(addr);
+}
+
+void *ExecutableAllocator::Allocation::codeStart() const
 {
     return reinterpret_cast<void*>(addr + exceptionHandlerSize());
 }
diff --git a/src/qml/jsruntime/qv4executableallocator_p.h b/src/qml/jsruntime/qv4executableallocator_p.h
index f98f2c7d33..4735fb151f 100644
--- a/src/qml/jsruntime/qv4executableallocator_p.h
+++ b/src/qml/jsruntime/qv4executableallocator_p.h
@@ -86,8 +86,14 @@ public:
             , free(true)
         {}
 
-        void *exceptionHandler() const;
-        void *start() const;
+        void *memoryStart() const;
+        size_t memorySize() const { return size; }
+
+        void *exceptionHandlerStart() const;
+        size_t exceptionHandlerSize() const;
+
+        void *codeStart() const;
+
         void invalidate() { addr = 0; }
         bool isValid() const { return addr != 0; }
         void deallocate(ExecutableAllocator *allocator);
diff --git a/src/qml/jsruntime/qv4functiontable_win64.cpp b/src/qml/jsruntime/qv4functiontable_win64.cpp
index fc13dc2602..0cb98641cd 100644
--- a/src/qml/jsruntime/qv4functiontable_win64.cpp
+++ b/src/qml/jsruntime/qv4functiontable_win64.cpp
@@ -106,7 +106,7 @@ struct ExceptionHandlerRecord
 void generateFunctionTable(Function *, JSC::MacroAssemblerCodeRef *codeRef)
 {
     ExceptionHandlerRecord *record = reinterpret_cast<ExceptionHandlerRecord *>(
-                codeRef->executableMemory()->exceptionHandler());
+                codeRef->executableMemory()->exceptionHandlerStart());
 
     record->info.Version             = 1;
     record->info.Flags               = 0;
@@ -136,7 +136,7 @@ void generateFunctionTable(Function *, JSC::MacroAssemblerCodeRef *codeRef)
 void destroyFunctionTable(Function *, JSC::MacroAssemblerCodeRef *codeRef)
 {
     ExceptionHandlerRecord *record = reinterpret_cast<ExceptionHandlerRecord *>(
-                codeRef->executableMemory()->exceptionHandler());
+                codeRef->executableMemory()->exceptionHandlerStart());
     if (!RtlDeleteFunctionTable(&record->handler)) {
         const unsigned int errorCode = GetLastError();
         qWarning() << "Failed to remove win64 unwind hook. Error code:" << errorCode;
-- 
2.31.1

