• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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    };
MemoryMapping()24    MemoryMapping() : map_(NULL), size_(0) {}
~MemoryMapping()25    ~MemoryMapping() {}
26  
27    // Return current mapping address.
Get()28    void* Get() { return map_; }
GetSize()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.
Allocate(void * address,size_t size,Protection prot,int fd)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.
SetProtection(Protection prot)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.
Deallocate()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:
Release()77    void* Release() {
78      void* ret = map_;
79      map_ = NULL;
80      return ret;
81    }
82  
~ScopedMemoryMapping()83    ~ScopedMemoryMapping() { Deallocate(); }
84  };
85  
86  }  // namespace crazy
87  
88  #endif  // CRAZY_LINKER_MEMORY_MAPPING_H
89