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