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