summaryrefslogtreecommitdiff
path: root/include/lldb/Target/Memory.h
blob: 05ff22a3f66b354fab120734e301cb81d0a72de0 (plain)
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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
//===-- Memory.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 liblldb_Memory_h_
#define liblldb_Memory_h_

#include <map>
#include <mutex>
#include <vector>


#include "lldb/Core/RangeMap.h"
#include "lldb/lldb-private.h"

namespace lldb_private {
//----------------------------------------------------------------------
// A class to track memory that was read from a live process between
// runs.
//----------------------------------------------------------------------
class MemoryCache {
public:
  //------------------------------------------------------------------
  // Constructors and Destructors
  //------------------------------------------------------------------
  MemoryCache(Process &process);

  ~MemoryCache();

  void Clear(bool clear_invalid_ranges = false);

  void Flush(lldb::addr_t addr, size_t size);

  size_t Read(lldb::addr_t addr, void *dst, size_t dst_len, Status &error);

  uint32_t GetMemoryCacheLineSize() const { return m_L2_cache_line_byte_size; }

  void AddInvalidRange(lldb::addr_t base_addr, lldb::addr_t byte_size);

  bool RemoveInvalidRange(lldb::addr_t base_addr, lldb::addr_t byte_size);

  // Allow external sources to populate data into the L1 memory cache
  void AddL1CacheData(lldb::addr_t addr, const void *src, size_t src_len);

  void AddL1CacheData(lldb::addr_t addr,
                      const lldb::DataBufferSP &data_buffer_sp);

protected:
  typedef std::map<lldb::addr_t, lldb::DataBufferSP> BlockMap;
  typedef RangeArray<lldb::addr_t, lldb::addr_t, 4> InvalidRanges;
  typedef Range<lldb::addr_t, lldb::addr_t> AddrRange;
  //------------------------------------------------------------------
  // Classes that inherit from MemoryCache can see and modify these
  //------------------------------------------------------------------
  std::recursive_mutex m_mutex;
  BlockMap m_L1_cache; // A first level memory cache whose chunk sizes vary that
                       // will be used only if the memory read fits entirely in
                       // a chunk
  BlockMap m_L2_cache; // A memory cache of fixed size chinks
                       // (m_L2_cache_line_byte_size bytes in size each)
  InvalidRanges m_invalid_ranges;
  Process &m_process;
  uint32_t m_L2_cache_line_byte_size;

private:
  DISALLOW_COPY_AND_ASSIGN(MemoryCache);
};

    

class AllocatedBlock {
public:
  AllocatedBlock(lldb::addr_t addr, uint32_t byte_size, uint32_t permissions,
                 uint32_t chunk_size);

  ~AllocatedBlock();

  lldb::addr_t ReserveBlock(uint32_t size);

  bool FreeBlock(lldb::addr_t addr);

  lldb::addr_t GetBaseAddress() const { return m_range.GetRangeBase(); }

  uint32_t GetByteSize() const { return m_range.GetByteSize(); }

  uint32_t GetPermissions() const { return m_permissions; }

  uint32_t GetChunkSize() const { return m_chunk_size; }

  bool Contains(lldb::addr_t addr) const {
    return m_range.Contains(addr);
  }

protected:
  uint32_t TotalChunks() const { return GetByteSize() / GetChunkSize(); }

  uint32_t CalculateChunksNeededForSize(uint32_t size) const {
    return (size + m_chunk_size - 1) / m_chunk_size;
  }
  // Base address of this block of memory 4GB of chunk should be enough.
  Range<lldb::addr_t, uint32_t> m_range;
  // Permissions for this memory (logical OR of lldb::Permissions bits)
  const uint32_t m_permissions;
  // The size of chunks that the memory at m_addr is divied up into.
  const uint32_t m_chunk_size;
  // A sorted list of free address ranges.
  RangeVector<lldb::addr_t, uint32_t> m_free_blocks;
  // A sorted list of reserved address.
  RangeVector<lldb::addr_t, uint32_t> m_reserved_blocks;
};

//----------------------------------------------------------------------
// A class that can track allocated memory and give out allocated memory
// without us having to make an allocate/deallocate call every time we need
// some memory in a process that is being debugged.
//----------------------------------------------------------------------
class AllocatedMemoryCache {
public:
  //------------------------------------------------------------------
  // Constructors and Destructors
  //------------------------------------------------------------------
  AllocatedMemoryCache(Process &process);

  ~AllocatedMemoryCache();

  void Clear();

  lldb::addr_t AllocateMemory(size_t byte_size, uint32_t permissions,
                              Status &error);

  bool DeallocateMemory(lldb::addr_t ptr);

protected:
  typedef std::shared_ptr<AllocatedBlock> AllocatedBlockSP;

  AllocatedBlockSP AllocatePage(uint32_t byte_size, uint32_t permissions,
                                uint32_t chunk_size, Status &error);

  //------------------------------------------------------------------
  // Classes that inherit from MemoryCache can see and modify these
  //------------------------------------------------------------------
  Process &m_process;
  std::recursive_mutex m_mutex;
  typedef std::multimap<uint32_t, AllocatedBlockSP> PermissionsToBlockMap;
  PermissionsToBlockMap m_memory_map;

private:
  DISALLOW_COPY_AND_ASSIGN(AllocatedMemoryCache);
};

} // namespace lldb_private

#endif // liblldb_Memory_h_