reference, declarationdefinition
definition → references, declarations, derived classes, virtual overrides
reference to multiple definitions → definitions
unreferenced
    1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118
  119
  120
  121
  122
  123
  124
  125
  126
  127
  128
  129
  130
  131
  132
  133
  134
  135
  136
//===-- IRMemoryMap.h -------------------------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef lldb_IRMemoryMap_h_
#define lldb_IRMemoryMap_h_

#include "lldb/Utility/DataBufferHeap.h"
#include "lldb/Utility/UserID.h"
#include "lldb/lldb-public.h"

#include <map>

namespace lldb_private {

/// \class IRMemoryMap IRMemoryMap.h "lldb/Expression/IRMemoryMap.h"
/// Encapsulates memory that may exist in the process but must
///     also be available in the host process.
///
/// This class encapsulates a group of memory objects that must be readable or
/// writable from the host process regardless of whether the process exists.
/// This allows the IR interpreter as well as JITted code to access the same
/// memory.  All allocations made by this class are represented as disjoint
/// intervals.
///
/// Point queries against this group of memory objects can be made by the
/// address in the tar at which they reside.  If the inferior does not exist,
/// allocations still get made-up addresses.  If an inferior appears at some
/// point, then those addresses need to be re-mapped.
class IRMemoryMap {
public:
  IRMemoryMap(lldb::TargetSP target_sp);
  ~IRMemoryMap();

  enum AllocationPolicy : uint8_t {
    eAllocationPolicyInvalid =
        0, ///< It is an error for an allocation to have this policy.
    eAllocationPolicyHostOnly, ///< This allocation was created in the host and
                               ///will never make it into the process.
    ///< It is an error to create other types of allocations while such
    ///allocations exist.
    eAllocationPolicyMirror, ///< The intent is that this allocation exist both
                             ///in the host and the process and have
                             ///< the same content in both.
    eAllocationPolicyProcessOnly ///< The intent is that this allocation exist
                                 ///only in the process.
  };

  lldb::addr_t Malloc(size_t size, uint8_t alignment, uint32_t permissions,
                      AllocationPolicy policy, bool zero_memory, Status &error);
  void Leak(lldb::addr_t process_address, Status &error);
  void Free(lldb::addr_t process_address, Status &error);

  void WriteMemory(lldb::addr_t process_address, const uint8_t *bytes,
                   size_t size, Status &error);
  void WriteScalarToMemory(lldb::addr_t process_address, Scalar &scalar,
                           size_t size, Status &error);
  void WritePointerToMemory(lldb::addr_t process_address, lldb::addr_t address,
                            Status &error);
  void ReadMemory(uint8_t *bytes, lldb::addr_t process_address, size_t size,
                  Status &error);
  void ReadScalarFromMemory(Scalar &scalar, lldb::addr_t process_address,
                            size_t size, Status &error);
  void ReadPointerFromMemory(lldb::addr_t *address,
                             lldb::addr_t process_address, Status &error);
  bool GetAllocSize(lldb::addr_t address, size_t &size);
  void GetMemoryData(DataExtractor &extractor, lldb::addr_t process_address,
                     size_t size, Status &error);

  lldb::ByteOrder GetByteOrder();
  uint32_t GetAddressByteSize();

  // This function can return NULL.
  ExecutionContextScope *GetBestExecutionContextScope() const;

  lldb::TargetSP GetTarget() { return m_target_wp.lock(); }

protected:
  // This function should only be used if you know you are using the JIT. Any
  // other cases should use GetBestExecutionContextScope().

  lldb::ProcessWP &GetProcessWP() { return m_process_wp; }

private:
  struct Allocation {
    lldb::addr_t
        m_process_alloc; ///< The (unaligned) base for the remote allocation.
    lldb::addr_t
        m_process_start; ///< The base address of the allocation in the process.
    size_t m_size;       ///< The size of the requested allocation.
    DataBufferHeap m_data;

    /// Flags. Keep these grouped together to avoid structure padding.
    AllocationPolicy m_policy;
    bool m_leak;
    uint8_t m_permissions; ///< The access permissions on the memory in the
                           /// process. In the host, the memory is always
                           /// read/write.
    uint8_t m_alignment;   ///< The alignment of the requested allocation.

  public:
    Allocation(lldb::addr_t process_alloc, lldb::addr_t process_start,
               size_t size, uint32_t permissions, uint8_t alignment,
               AllocationPolicy m_policy);

    DISALLOW_COPY_AND_ASSIGN(Allocation);
  };

  static_assert(sizeof(Allocation) <=
                    (4 * sizeof(lldb::addr_t)) + sizeof(DataBufferHeap),
                "IRMemoryMap::Allocation is larger than expected");

  lldb::ProcessWP m_process_wp;
  lldb::TargetWP m_target_wp;
  typedef std::map<lldb::addr_t, Allocation> AllocationMap;
  AllocationMap m_allocations;

  lldb::addr_t FindSpace(size_t size);
  bool ContainsHostOnlyAllocations();
  AllocationMap::iterator FindAllocation(lldb::addr_t addr, size_t size);

  // Returns true if the given allocation intersects any allocation in the
  // memory map.
  bool IntersectsAllocation(lldb::addr_t addr, size_t size) const;

  // Returns true if the two given allocations intersect each other.
  static bool AllocationsIntersect(lldb::addr_t addr1, size_t size1,
                                   lldb::addr_t addr2, size_t size2);
};
}

#endif