1// Copyright 2014 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
14namespace crazy {
15
16// Helper class for a memory mapping. This is _not_ scoped.
17class 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.
75class 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