From 4a984c15dde72e074b2d66e484387cbe0d53130d Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Wed, 24 Apr 2024 13:33:51 -0700 Subject: [PATCH] QResource: add support for duplicating mapped memory on macOS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Similar to the Linux solution, this avoids allocating heap memory in the implementation of QFile::map() calls with MapPrivateOption. Unlike the Linux solution, the macOS one cannot duplicate resources present in read-only sections of binaries, only those loaded from files with mmap() (QResource::registerResource()), because the max_prot setting on the source does not have the VM_PROT_WRITE bit set and I could not find a way to reset it to force a copy-on-write. Change-Id: I6979d02a7395405cbf23fffd17c951949c71ec20 Reviewed-by: Oswald Buddenhagen Reviewed-by: Tor Arne Vestbø --- src/corelib/io/qresource.cpp | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/corelib/io/qresource.cpp b/src/corelib/io/qresource.cpp index acb6b786c1..581e1e75ef 100644 --- a/src/corelib/io/qresource.cpp +++ b/src/corelib/io/qresource.cpp @@ -39,6 +39,9 @@ # ifdef Q_OS_LINUX // since 5.7, so define in case we're being compiled with older kernel headers # define MREMAP_DONTUNMAP 4 +# elif defined(Q_OS_DARWIN) +# include +# include # endif #endif #ifdef Q_OS_WIN @@ -1741,6 +1744,25 @@ bool QResourceFileEnginePrivate::mapUncompressed_sys() munmap(ptr, r.size); return false; } +#elif defined(Q_OS_DARWIN) + mach_port_t self = mach_task_self(); + vm_address_t addr = 0; + vm_address_t mask = 0; + bool anywhere = true; + bool copy = true; + vm_prot_t cur_prot = VM_PROT_READ | VM_PROT_WRITE; + vm_prot_t max_prot = VM_PROT_ALL; + kern_return_t res = vm_remap(self, &addr, r.size, mask, anywhere, + self, vm_address_t(r.begin), copy, &cur_prot, + &max_prot, VM_INHERIT_DEFAULT); + if (res != KERN_SUCCESS) + return false; + + ptr = reinterpret_cast(addr); + if ((max_prot & VM_PROT_WRITE) == 0 || mprotect(ptr, r.size, PROT_READ | PROT_WRITE) != 0) { + munmap(ptr, r.size); + return false; + } #endif if (!ptr)