[llvm] r360221 - [Support] Add error handling to sys::Process::getPageSize().

Lang Hames via llvm-commits llvm-commits at lists.llvm.org
Tue May 7 19:11:07 PDT 2019


Author: lhames
Date: Tue May  7 19:11:07 2019
New Revision: 360221

URL: http://llvm.org/viewvc/llvm-project?rev=360221&view=rev
Log:
[Support] Add error handling to sys::Process::getPageSize().

This patch changes the return type of sys::Process::getPageSize to
Expected<unsigned> to account for the fact that the underlying syscalls used to
obtain the page size may fail (see below).

For clients who use the page size as an optimization only this patch adds a new
method, getPageSizeEstimate, which calls through to getPageSize but discards
any error returned and substitues a "reasonable" page size estimate estimate
instead. All existing LLVM clients are updated to call getPageSizeEstimate
rather than getPageSize.

On Unix, sys::Process::getPageSize is implemented in terms of getpagesize or
sysconf, depending on which macros are set. The sysconf call is documented to
return -1 on failure. On Darwin getpagesize is implemented in terms of sysconf
and may also fail (though the manpage documentation does not mention this).
These failures have been observed in practice when highly restrictive sandbox
permissions have been applied. Without this patch, the result is that
getPageSize returns -1, which wreaks havoc on any subsequent code that was
assuming a sane page size value.

<rdar://problem/41654857>

Reviewers: dblaikie, echristo

Subscribers: kristina, llvm-commits

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D59107

Modified:
    llvm/trunk/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h
    llvm/trunk/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetServer.h
    llvm/trunk/include/llvm/Support/Process.h
    llvm/trunk/lib/ExecutionEngine/JITLink/JITLink.cpp
    llvm/trunk/lib/ExecutionEngine/Orc/OrcABISupport.cpp
    llvm/trunk/lib/ExecutionEngine/SectionMemoryManager.cpp
    llvm/trunk/lib/Support/MemoryBuffer.cpp
    llvm/trunk/lib/Support/Unix/Memory.inc
    llvm/trunk/lib/Support/Unix/Path.inc
    llvm/trunk/lib/Support/Unix/Process.inc
    llvm/trunk/lib/Support/Windows/Process.inc
    llvm/trunk/unittests/Support/MemoryTest.cpp

Modified: llvm/trunk/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h?rev=360221&r1=360220&r2=360221&view=diff
==============================================================================
--- llvm/trunk/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h (original)
+++ llvm/trunk/include/llvm/ExecutionEngine/Orc/IndirectionUtils.h Tue May  7 19:11:07 2019
@@ -146,13 +146,13 @@ private:
     std::error_code EC;
     auto TrampolineBlock =
         sys::OwningMemoryBlock(sys::Memory::allocateMappedMemory(
-            sys::Process::getPageSize(), nullptr,
+            sys::Process::getPageSizeEstimate(), nullptr,
             sys::Memory::MF_READ | sys::Memory::MF_WRITE, EC));
     if (EC)
       return errorCodeToError(EC);
 
     unsigned NumTrampolines =
-        (sys::Process::getPageSize() - ORCABI::PointerSize) /
+        (sys::Process::getPageSizeEstimate() - ORCABI::PointerSize) /
         ORCABI::TrampolineSize;
 
     uint8_t *TrampolineMem = static_cast<uint8_t *>(TrampolineBlock.base());

Modified: llvm/trunk/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetServer.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetServer.h?rev=360221&r1=360220&r2=360221&view=diff
==============================================================================
--- llvm/trunk/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetServer.h (original)
+++ llvm/trunk/include/llvm/ExecutionEngine/Orc/OrcRemoteTargetServer.h Tue May  7 19:11:07 2019
@@ -299,13 +299,13 @@ private:
     std::error_code EC;
     auto TrampolineBlock =
         sys::OwningMemoryBlock(sys::Memory::allocateMappedMemory(
-            sys::Process::getPageSize(), nullptr,
+            sys::Process::getPageSizeEstimate(), nullptr,
             sys::Memory::MF_READ | sys::Memory::MF_WRITE, EC));
     if (EC)
       return errorCodeToError(EC);
 
     uint32_t NumTrampolines =
-        (sys::Process::getPageSize() - TargetT::PointerSize) /
+        (sys::Process::getPageSizeEstimate() - TargetT::PointerSize) /
         TargetT::TrampolineSize;
 
     uint8_t *TrampolineMem = static_cast<uint8_t *>(TrampolineBlock.base());
@@ -335,7 +335,7 @@ private:
   handleGetRemoteInfo() {
     std::string ProcessTriple = sys::getProcessTriple();
     uint32_t PointerSize = TargetT::PointerSize;
-    uint32_t PageSize = sys::Process::getPageSize();
+    uint32_t PageSize = sys::Process::getPageSizeEstimate();
     uint32_t TrampolineSize = TargetT::TrampolineSize;
     uint32_t IndirectStubSize = TargetT::IndirectStubsInfo::StubSize;
     LLVM_DEBUG(dbgs() << "  Remote info:\n"

Modified: llvm/trunk/include/llvm/Support/Process.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/Process.h?rev=360221&r1=360220&r2=360221&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Support/Process.h (original)
+++ llvm/trunk/include/llvm/Support/Process.h Tue May  7 19:11:07 2019
@@ -28,6 +28,7 @@
 #include "llvm/Support/Allocator.h"
 #include "llvm/Support/Chrono.h"
 #include "llvm/Support/DataTypes.h"
+#include "llvm/Support/Error.h"
 #include <system_error>
 
 namespace llvm {
@@ -41,7 +42,25 @@ namespace sys {
 /// current executing process.
 class Process {
 public:
-  static unsigned getPageSize();
+  /// Get the process's page size.
+  /// This may fail if the underlying syscall returns an error. In most cases,
+  /// page size information is used for optimization, and this error can be
+  /// safely discarded by calling consumeError, and an estimated page size
+  /// substituted instead.
+  static Expected<unsigned> getPageSize();
+
+  /// Get the process's estimated page size.
+  /// This function always succeeds, but if the underlying syscall to determine
+  /// the page size fails then this will silently return an estimated page size.
+  /// The estimated page size is guaranteed to be a power of 2.
+  static unsigned getPageSizeEstimate() {
+    if (auto PageSize = getPageSize())
+      return *PageSize;
+    else {
+      consumeError(PageSize.takeError());
+      return 4096;
+    }
+  }
 
   /// Return process memory usage.
   /// This static function will return the total amount of memory allocated

Modified: llvm/trunk/lib/ExecutionEngine/JITLink/JITLink.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ExecutionEngine/JITLink/JITLink.cpp?rev=360221&r1=360220&r2=360221&view=diff
==============================================================================
--- llvm/trunk/lib/ExecutionEngine/JITLink/JITLink.cpp (original)
+++ llvm/trunk/lib/ExecutionEngine/JITLink/JITLink.cpp Tue May  7 19:11:07 2019
@@ -194,12 +194,12 @@ InProcessMemoryManager::allocate(const S
   for (auto &KV : Request) {
     auto &Seg = KV.second;
 
-    if (Seg.getContentAlignment() > sys::Process::getPageSize())
+    if (Seg.getContentAlignment() > sys::Process::getPageSizeEstimate())
       return make_error<StringError>("Cannot request higher than page "
                                      "alignment",
                                      inconvertibleErrorCode());
 
-    if (sys::Process::getPageSize() % Seg.getContentAlignment() != 0)
+    if (sys::Process::getPageSizeEstimate() % Seg.getContentAlignment() != 0)
       return make_error<StringError>("Page size is not a multiple of "
                                      "alignment",
                                      inconvertibleErrorCode());

Modified: llvm/trunk/lib/ExecutionEngine/Orc/OrcABISupport.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ExecutionEngine/Orc/OrcABISupport.cpp?rev=360221&r1=360220&r2=360221&view=diff
==============================================================================
--- llvm/trunk/lib/ExecutionEngine/Orc/OrcABISupport.cpp (original)
+++ llvm/trunk/lib/ExecutionEngine/Orc/OrcABISupport.cpp Tue May  7 19:11:07 2019
@@ -147,7 +147,7 @@ Error OrcAArch64::emitIndirectStubsBlock
   const unsigned StubSize = IndirectStubsInfo::StubSize;
 
   // Emit at least MinStubs, rounded up to fill the pages allocated.
-  unsigned PageSize = sys::Process::getPageSize();
+  static const unsigned PageSize = sys::Process::getPageSizeEstimate();
   unsigned NumPages = ((MinStubs * StubSize) + (PageSize - 1)) / PageSize;
   unsigned NumStubs = (NumPages * PageSize) / StubSize;
 
@@ -229,7 +229,7 @@ Error OrcX86_64_Base::emitIndirectStubsB
   const unsigned StubSize = IndirectStubsInfo::StubSize;
 
   // Emit at least MinStubs, rounded up to fill the pages allocated.
-  unsigned PageSize = sys::Process::getPageSize();
+  static const unsigned PageSize = sys::Process::getPageSizeEstimate();
   unsigned NumPages = ((MinStubs * StubSize) + (PageSize - 1)) / PageSize;
   unsigned NumStubs = (NumPages * PageSize) / StubSize;
 
@@ -497,7 +497,7 @@ Error OrcI386::emitIndirectStubsBlock(In
   const unsigned StubSize = IndirectStubsInfo::StubSize;
 
   // Emit at least MinStubs, rounded up to fill the pages allocated.
-  unsigned PageSize = sys::Process::getPageSize();
+  static const unsigned PageSize = sys::Process::getPageSizeEstimate();
   unsigned NumPages = ((MinStubs * StubSize) + (PageSize - 1)) / PageSize;
   unsigned NumStubs = (NumPages * PageSize) / StubSize;
 
@@ -683,7 +683,7 @@ Error OrcMips32_Base::emitIndirectStubsB
   const unsigned StubSize = IndirectStubsInfo::StubSize;
 
   // Emit at least MinStubs, rounded up to fill the pages allocated.
-  unsigned PageSize = sys::Process::getPageSize();
+  static const unsigned PageSize = sys::Process::getPageSizeEstimate();
   unsigned NumPages = ((MinStubs * StubSize) + (PageSize - 1)) / PageSize;
   unsigned NumStubs = (NumPages * PageSize) / StubSize;
 
@@ -929,7 +929,7 @@ Error OrcMips64::emitIndirectStubsBlock(
   const unsigned StubSize = IndirectStubsInfo::StubSize;
 
   // Emit at least MinStubs, rounded up to fill the pages allocated.
-  unsigned PageSize = sys::Process::getPageSize();
+  static const unsigned PageSize = sys::Process::getPageSizeEstimate();
   unsigned NumPages = ((MinStubs * StubSize) + (PageSize - 1)) / PageSize;
   unsigned NumStubs = (NumPages * PageSize) / StubSize;
 

Modified: llvm/trunk/lib/ExecutionEngine/SectionMemoryManager.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ExecutionEngine/SectionMemoryManager.cpp?rev=360221&r1=360220&r2=360221&view=diff
==============================================================================
--- llvm/trunk/lib/ExecutionEngine/SectionMemoryManager.cpp (original)
+++ llvm/trunk/lib/ExecutionEngine/SectionMemoryManager.cpp Tue May  7 19:11:07 2019
@@ -172,7 +172,7 @@ bool SectionMemoryManager::finalizeMemor
 }
 
 static sys::MemoryBlock trimBlockToPageSize(sys::MemoryBlock M) {
-  static const size_t PageSize = sys::Process::getPageSize();
+  static const size_t PageSize = sys::Process::getPageSizeEstimate();
 
   size_t StartOverlap =
       (PageSize - ((uintptr_t)M.base() % PageSize)) % PageSize;
@@ -244,7 +244,7 @@ public:
                        unsigned Flags, std::error_code &EC) override {
     // allocateMappedMemory calls mmap(2). We round up a request size
     // to page size to get extra space for free.
-    static const size_t PageSize = sys::Process::getPageSize();
+    static const size_t PageSize = sys::Process::getPageSizeEstimate();
     size_t ReqBytes = (NumBytes + PageSize - 1) & ~(PageSize - 1);
     return sys::Memory::allocateMappedMemory(ReqBytes, NearBlock, Flags, EC);
   }

Modified: llvm/trunk/lib/Support/MemoryBuffer.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/MemoryBuffer.cpp?rev=360221&r1=360220&r2=360221&view=diff
==============================================================================
--- llvm/trunk/lib/Support/MemoryBuffer.cpp (original)
+++ llvm/trunk/lib/Support/MemoryBuffer.cpp Tue May  7 19:11:07 2019
@@ -417,7 +417,7 @@ static ErrorOr<std::unique_ptr<MB>>
 getOpenFileImpl(int FD, const Twine &Filename, uint64_t FileSize,
                 uint64_t MapSize, int64_t Offset, bool RequiresNullTerminator,
                 bool IsVolatile) {
-  static int PageSize = sys::Process::getPageSize();
+  static int PageSize = sys::Process::getPageSizeEstimate();
 
   // Default is to map the full file.
   if (MapSize == uint64_t(-1)) {

Modified: llvm/trunk/lib/Support/Unix/Memory.inc
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/Unix/Memory.inc?rev=360221&r1=360220&r2=360221&view=diff
==============================================================================
--- llvm/trunk/lib/Support/Unix/Memory.inc (original)
+++ llvm/trunk/lib/Support/Unix/Memory.inc Tue May  7 19:11:07 2019
@@ -103,7 +103,7 @@ Memory::allocateMappedMemory(size_t NumB
   // Use any near hint and the page size to set a page-aligned starting address
   uintptr_t Start = NearBlock ? reinterpret_cast<uintptr_t>(NearBlock->base()) +
                                       NearBlock->size() : 0;
-  static const size_t PageSize = Process::getPageSize();
+  static const size_t PageSize = Process::getPageSizeEstimate();
   if (Start && Start % PageSize)
     Start += PageSize - Start % PageSize;
 
@@ -149,7 +149,7 @@ Memory::releaseMappedMemory(MemoryBlock
 
 std::error_code
 Memory::protectMappedMemory(const MemoryBlock &M, unsigned Flags) {
-  static const size_t PageSize = Process::getPageSize();
+  static const size_t PageSize = Process::getPageSizeEstimate();
   if (M.Address == nullptr || M.Size == 0)
     return std::error_code();
 

Modified: llvm/trunk/lib/Support/Unix/Path.inc
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/Unix/Path.inc?rev=360221&r1=360220&r2=360221&view=diff
==============================================================================
--- llvm/trunk/lib/Support/Unix/Path.inc (original)
+++ llvm/trunk/lib/Support/Unix/Path.inc Tue May  7 19:11:07 2019
@@ -786,7 +786,7 @@ const char *mapped_file_region::const_da
 }
 
 int mapped_file_region::alignment() {
-  return Process::getPageSize();
+  return Process::getPageSizeEstimate();
 }
 
 std::error_code detail::directory_iterator_construct(detail::DirIterState &it,

Modified: llvm/trunk/lib/Support/Unix/Process.inc
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/Unix/Process.inc?rev=360221&r1=360220&r2=360221&view=diff
==============================================================================
--- llvm/trunk/lib/Support/Unix/Process.inc (original)
+++ llvm/trunk/lib/Support/Unix/Process.inc Tue May  7 19:11:07 2019
@@ -69,7 +69,7 @@ static std::pair<std::chrono::microsecon
 
 // On Cygwin, getpagesize() returns 64k(AllocationGranularity) and
 // offset in mmap(3) should be aligned to the AllocationGranularity.
-unsigned Process::getPageSize() {
+Expected<unsigned> Process::getPageSize() {
 #if defined(HAVE_GETPAGESIZE)
   static const int page_size = ::getpagesize();
 #elif defined(HAVE_SYSCONF)
@@ -77,6 +77,9 @@ unsigned Process::getPageSize() {
 #else
 #error Cannot get the page size on this machine
 #endif
+  if (page_size == -1)
+    return errorCodeToError(std::error_code(errno, std::generic_category()));
+
   return static_cast<unsigned>(page_size);
 }
 

Modified: llvm/trunk/lib/Support/Windows/Process.inc
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Support/Windows/Process.inc?rev=360221&r1=360220&r2=360221&view=diff
==============================================================================
--- llvm/trunk/lib/Support/Windows/Process.inc (original)
+++ llvm/trunk/lib/Support/Windows/Process.inc Tue May  7 19:11:07 2019
@@ -56,7 +56,7 @@ static unsigned computePageSize() {
   return static_cast<unsigned>(info.dwPageSize);
 }
 
-unsigned Process::getPageSize() {
+Expected<unsigned> Process::getPageSize() {
   static unsigned Ret = computePageSize();
   return Ret;
 }

Modified: llvm/trunk/unittests/Support/MemoryTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/Support/MemoryTest.cpp?rev=360221&r1=360220&r2=360221&view=diff
==============================================================================
--- llvm/trunk/unittests/Support/MemoryTest.cpp (original)
+++ llvm/trunk/unittests/Support/MemoryTest.cpp Tue May  7 19:11:07 2019
@@ -50,7 +50,7 @@ class MappedMemoryTest : public ::testin
 public:
   MappedMemoryTest() {
     Flags = GetParam();
-    PageSize = sys::Process::getPageSize();
+    PageSize = sys::Process::getPageSizeEstimate();
   }
 
 protected:




More information about the llvm-commits mailing list