diff --git a/interpreter/llvm/src/lib/ExecutionEngine/SectionMemoryManager.cpp b/interpreter/llvm/src/lib/ExecutionEngine/SectionMemoryManager.cpp index 1ad5f1740115b..08b54827e33db 100644 --- a/interpreter/llvm/src/lib/ExecutionEngine/SectionMemoryManager.cpp +++ b/interpreter/llvm/src/lib/ExecutionEngine/SectionMemoryManager.cpp @@ -83,6 +83,8 @@ uint8_t *SectionMemoryManager::allocateSection(MemoryGroup &MemGroup, // // FIXME: Initialize the Near member for each memory group to avoid // interleaving. + // Note: this would not be sufficient as the Near member is just a hint + // to mmap. std::error_code ec; sys::MemoryBlock MB = sys::Memory::allocateMappedMemory(RequiredSize, &MemGroup.Near, @@ -94,6 +96,35 @@ uint8_t *SectionMemoryManager::allocateSection(MemoryGroup &MemGroup, return nullptr; } + // To be sure that there is no interleaving, enforce the monotonic decrease + // of the memory adddress. This is required by libgcc's _Unwind_Find_FDE + // which does a linear search (of the top level dwarf objects) and note in the code + // "Note that pc_begin is sorted descending, and we expect objects to be + // non-overlapping. " + if (MemGroup.Near.base() && (size_t)MB.base() > (size_t)MemGroup.Near.base()) { + SmallVector MemToDelete; + while ((size_t)MB.base() > (size_t)MemGroup.Near.base()) { + // Hold on to the memory until we get an acceptable one + // just so that we are not given it back. + MemToDelete.push_back(MB); + MB = sys::Memory::allocateMappedMemory(RequiredSize, + &MemGroup.Near, + sys::Memory::MF_READ | + sys::Memory::MF_WRITE, + ec); + if (ec) { + for (sys::MemoryBlock &Block : MemToDelete) { + sys::Memory::releaseMappedMemory(Block); + } + // FIXME: Add error propagation to the interface. + return nullptr; + } + } + for (sys::MemoryBlock &Block : MemToDelete) { + sys::Memory::releaseMappedMemory(Block); + } + } + // Save this address as the basis for our next request MemGroup.Near = MB;