1f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 2f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// found in the LICENSE file. 4f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 5f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "crazy_linker_elf_relro.h" 6f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 7f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include <errno.h> 8f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include <limits.h> 9f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include <stdlib.h> 10f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 11f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "crazy_linker_elf_relocations.h" 12f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "crazy_linker_elf_view.h" 13f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "crazy_linker_memory_mapping.h" 14f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "crazy_linker_util.h" 15f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 16f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)namespace crazy { 17f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 18f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)namespace { 19f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 20f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)inline bool PageEquals(const char* p1, const char* p2) { 21f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return ::memcmp(p1, p2, PAGE_SIZE) == 0; 22f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 23f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 24f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Swap pages between |addr| and |addr + size| with the bytes 25f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// from the ashmem region identified by |fd|, starting from 26f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// a given |offset|. On failure return false and set |error| message. 27f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)bool SwapPagesFromFd(void* addr, 28f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) size_t size, 29f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) int fd, 30f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) size_t offset, 31f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) Error* error) { 32f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Unmap current pages. 33f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (::munmap(addr, size) < 0) { 34f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) error->Format("%s: Could not unmap %p-%p: %s", 35f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) __FUNCTION__, 36f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) addr, 37f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) (char*)addr + size, 38f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) strerror(errno)); 39f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return false; 40f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 41f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 42f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Remap the fd pages at the same location now. 43f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) void* new_map = ::mmap(addr, 44f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) size, 45f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) PROT_READ, 46f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) MAP_FIXED | MAP_SHARED, 47f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) fd, 48f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) static_cast<off_t>(offset)); 49f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (new_map == MAP_FAILED) { 50f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) char* p = reinterpret_cast<char*>(addr); 51f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) error->Format("%s: Could not map %p-%p: %s", 52f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) __FUNCTION__, 53f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) p, 54f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) p + size, 55f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) strerror(errno)); 56f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return false; 57f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 58f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 59f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// TODO(digit): Is this necessary? 60f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#ifdef __arm__ 61f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) __clear_cache(addr, (char*)addr + size); 62f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#endif 63f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 64f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Done. 65f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return true; 66f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 67f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 68f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} // namespace 69f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 70f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)bool SharedRelro::Allocate(size_t relro_size, 71f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) const char* library_name, 72f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) Error* error) { 73f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Allocate a new ashmem region. 74f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) String name("RELRO:"); 75f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) name += library_name; 76f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (!ashmem_.Allocate(relro_size, name.c_str())) { 77f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) error->Format("Could not allocate RELRO ashmem region for %s: %s", 78f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) library_name, 79f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) strerror(errno)); 80f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return false; 81f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 82f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 83f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) start_ = 0; 84f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) size_ = relro_size; 85f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return true; 86f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 87f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 88f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)bool SharedRelro::CopyFrom(size_t relro_start, 89f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) size_t relro_size, 90f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) Error* error) { 91f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Map it in the process. 92f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ScopedMemoryMapping map; 93f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (!map.Allocate(NULL, relro_size, MemoryMapping::CAN_WRITE, ashmem_.fd())) { 94f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) error->Format("Could not allocate RELRO mapping: %s", strerror(errno)); 95f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return false; 96f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 97f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 98f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Copy process' RELRO into it. 99f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ::memcpy(map.Get(), reinterpret_cast<void*>(relro_start), relro_size); 100f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 101f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Unmap it. 102f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) map.Deallocate(); 103f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 104f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Everything's good. 105f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) start_ = relro_start; 106f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) size_ = relro_size; 107f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return true; 108f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 109f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 110f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)bool SharedRelro::CopyFromRelocated(const ElfView* view, 111f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) size_t load_address, 112f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) size_t relro_start, 113f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) size_t relro_size, 114f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) Error* error) { 115f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Offset of RELRO section in current library. 116f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) size_t relro_offset = relro_start - view->load_address(); 117f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 118f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ElfRelocations relocations; 119f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (!relocations.Init(view, error)) 120f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return false; 121f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 122f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Map the region in memory (any address). 123f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ScopedMemoryMapping map; 124f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (!map.Allocate( 125f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) NULL, relro_size, MemoryMapping::CAN_READ_WRITE, ashmem_.fd())) { 126f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) error->Format("Could not allocate RELRO mapping for: %s", strerror(errno)); 127f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return false; 128f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 129f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 130f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Copy and relocate. 131f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) relocations.CopyAndRelocate(relro_start, 132f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) reinterpret_cast<size_t>(map.Get()), 133f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) load_address + relro_offset, 134f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) relro_size); 135f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Unmap it. 136f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) map.Deallocate(); 137f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) start_ = load_address + relro_offset; 138f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) size_ = relro_size; 139f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return true; 140f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 141f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 142f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)bool SharedRelro::ForceReadOnly(Error* error) { 143f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Ensure the ashmem region content isn't writable anymore. 144f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (!ashmem_.SetProtectionFlags(PROT_READ)) { 145f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) error->Format("Could not make RELRO ashmem region read-only: %s", 146f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) strerror(errno)); 147f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return false; 148f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 149f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return true; 150f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 151f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 152f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)bool SharedRelro::InitFrom(size_t relro_start, 153f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) size_t relro_size, 154f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) int ashmem_fd, 155f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) Error* error) { 156f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Create temporary mapping of the ashmem region. 157f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ScopedMemoryMapping fd_map; 158f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 159f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) LOG("%s: Entering addr=%p size=%p fd=%d\n", 160f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) __FUNCTION__, 161f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) (void*)relro_start, 162f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) (void*)relro_size, 163f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ashmem_fd); 164f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 165f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Sanity check: Ashmem file descriptor must be read-only. 166f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (!AshmemRegion::CheckFileDescriptorIsReadOnly(ashmem_fd)) { 167f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) error->Format("Ashmem file descriptor is not read-only: %s\n", 168f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) strerror(errno)); 169f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return false; 170f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 171f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 172f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (!fd_map.Allocate(NULL, relro_size, MemoryMapping::CAN_READ, ashmem_fd)) { 173f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) error->Format("Cannot map RELRO ashmem region as read-only: %s\n", 174f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) strerror(errno)); 175f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return false; 176f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 177f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 178f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) LOG("%s: mapping allocated at %p\n", __FUNCTION__, fd_map.Get()); 179f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 180f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) char* cur_page = reinterpret_cast<char*>(relro_start); 181f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) char* fd_page = static_cast<char*>(fd_map.Get()); 182f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) size_t p = 0; 183f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) size_t size = relro_size; 184f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) size_t similar_size = 0; 185f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 186f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) do { 187f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Skip over dissimilar pages. 188f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) while (p < size && !PageEquals(cur_page + p, fd_page + p)) { 189f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) p += PAGE_SIZE; 190f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 191f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 192f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Count similar pages. 193f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) size_t p2 = p; 194f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) while (p2 < size && PageEquals(cur_page + p2, fd_page + p2)) { 195f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) p2 += PAGE_SIZE; 196f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 197f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 198f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (p2 > p) { 199f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Swap pages between |pos| and |pos2|. 200f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) LOG("%s: Swap pages at %p-%p\n", 201f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) __FUNCTION__, 202f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) cur_page + p, 203f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) cur_page + p2); 204f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (!SwapPagesFromFd(cur_page + p, p2 - p, ashmem_fd, p, error)) 205f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return false; 206f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 207f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) similar_size += (p2 - p); 208f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 209f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 210f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) p = p2; 211f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } while (p < size); 212f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 213f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) LOG("%s: Swapped %d pages over %d (%d %%, %d KB not shared)\n", 214f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) __FUNCTION__, 215f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) similar_size / PAGE_SIZE, 216f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) size / PAGE_SIZE, 217f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) similar_size * 100 / size, 218f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) (size - similar_size) / 4096); 219f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 220f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (similar_size == 0) 221f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return false; 222f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 223f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) start_ = relro_start; 224f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) size_ = relro_size; 225f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return true; 226f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 227f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 228f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} // namespace crazy 229