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)#ifndef CRAZY_LINKER_MEMORY_MAPPING_H 6f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#define CRAZY_LINKER_MEMORY_MAPPING_H 7f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 8f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include <errno.h> 9f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include <sys/mman.h> 10f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 11f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "crazy_linker_debug.h" 12f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include "crazy_linker_error.h" 13f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 14f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)namespace crazy { 15f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 16f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Helper class for a memory mapping. This is _not_ scoped. 17f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)class MemoryMapping { 18f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) public: 19f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) enum Protection { 20f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) CAN_READ = PROT_READ, 21f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) CAN_WRITE = PROT_WRITE, 22f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) CAN_READ_WRITE = PROT_READ | PROT_WRITE 23f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) }; 24f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) MemoryMapping() : map_(NULL), size_(0) {} 25f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ~MemoryMapping() {} 26f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 27f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Return current mapping address. 28f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) void* Get() { return map_; } 29f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) size_t GetSize() const { return size_; } 30f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 31f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Allocate a new mapping. 32f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // |address| is either NULL or a fixed memory address. 33f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // |size| is the page-aligned size, must be > 0. 34f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // |prot| are the desired protection bit flags. 35f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // |fd| is -1 (for anonymous mappings), or a valid file descriptor. 36f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // on failure, return false and sets errno. 37f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) bool Allocate(void* address, size_t size, Protection prot, int fd) { 38f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) int flags = (fd >= 0) ? MAP_SHARED : MAP_ANONYMOUS; 39f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (address) 40f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) flags |= MAP_FIXED; 41f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 42f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) size_ = size; 43f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) map_ = ::mmap(address, size_, static_cast<int>(prot), flags, fd, 0); 44f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (map_ == MAP_FAILED) { 45f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) map_ = NULL; 46f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return false; 47f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 48f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 49f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return true; 50f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 51f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 52f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Change the protection flags of the mapping. 53f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // On failure, return false and sets errno. 54f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) bool SetProtection(Protection prot) { 55f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (!map_ || ::mprotect(map_, size_, static_cast<int>(prot)) < 0) 56f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return false; 57f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return true; 58f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 59f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 60f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Deallocate an existing mapping, if any. 61f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) void Deallocate() { 62f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (map_) { 63f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ::munmap(map_, size_); 64f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) map_ = NULL; 65f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 66f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 67f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 68f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) protected: 69f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) void* map_; 70f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) size_t size_; 71f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}; 72f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 73f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Helper class for a memory mapping that is automatically 74f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// unmapped on scope exit, unless its Release() method is called. 75f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)class ScopedMemoryMapping : public MemoryMapping { 76f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) public: 77f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) void* Release() { 78f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) void* ret = map_; 79f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) map_ = NULL; 80f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) return ret; 81f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 82f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 83f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ~ScopedMemoryMapping() { Deallocate(); } 84f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}; 85f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 86f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} // namespace crazy 87f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 88f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#endif // CRAZY_LINKER_MEMORY_MAPPING_H 89