1 /* 2 * Copyright (C) 2016 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef _LIBUNWINDSTACK_MEMORY_H 18 #define _LIBUNWINDSTACK_MEMORY_H 19 20 #include <stdint.h> 21 #include <sys/types.h> 22 #include <unistd.h> 23 24 #include <atomic> 25 #include <memory> 26 #include <string> 27 #include <vector> 28 29 namespace unwindstack { 30 31 class Memory { 32 public: 33 Memory() = default; 34 virtual ~Memory() = default; 35 36 static std::shared_ptr<Memory> CreateProcessMemory(pid_t pid); 37 38 virtual bool ReadString(uint64_t addr, std::string* string, uint64_t max_read = UINT64_MAX); 39 40 virtual size_t Read(uint64_t addr, void* dst, size_t size) = 0; 41 42 bool ReadFully(uint64_t addr, void* dst, size_t size); 43 ReadField(uint64_t addr,void * start,void * field,size_t size)44 inline bool ReadField(uint64_t addr, void* start, void* field, size_t size) { 45 if (reinterpret_cast<uintptr_t>(field) < reinterpret_cast<uintptr_t>(start)) { 46 return false; 47 } 48 uint64_t offset = reinterpret_cast<uintptr_t>(field) - reinterpret_cast<uintptr_t>(start); 49 if (__builtin_add_overflow(addr, offset, &offset)) { 50 return false; 51 } 52 // The read will check if offset + size overflows. 53 return ReadFully(offset, field, size); 54 } 55 Read32(uint64_t addr,uint32_t * dst)56 inline bool Read32(uint64_t addr, uint32_t* dst) { 57 return ReadFully(addr, dst, sizeof(uint32_t)); 58 } 59 Read64(uint64_t addr,uint64_t * dst)60 inline bool Read64(uint64_t addr, uint64_t* dst) { 61 return ReadFully(addr, dst, sizeof(uint64_t)); 62 } 63 }; 64 65 class MemoryBuffer : public Memory { 66 public: 67 MemoryBuffer() = default; 68 virtual ~MemoryBuffer() = default; 69 70 size_t Read(uint64_t addr, void* dst, size_t size) override; 71 72 uint8_t* GetPtr(size_t offset); 73 Resize(size_t size)74 void Resize(size_t size) { raw_.resize(size); } 75 Size()76 uint64_t Size() { return raw_.size(); } 77 78 private: 79 std::vector<uint8_t> raw_; 80 }; 81 82 class MemoryFileAtOffset : public Memory { 83 public: 84 MemoryFileAtOffset() = default; 85 virtual ~MemoryFileAtOffset(); 86 87 bool Init(const std::string& file, uint64_t offset, uint64_t size = UINT64_MAX); 88 89 size_t Read(uint64_t addr, void* dst, size_t size) override; 90 Size()91 size_t Size() { return size_; } 92 93 void Clear(); 94 95 protected: 96 size_t size_ = 0; 97 size_t offset_ = 0; 98 uint8_t* data_ = nullptr; 99 }; 100 101 class MemoryRemote : public Memory { 102 public: MemoryRemote(pid_t pid)103 MemoryRemote(pid_t pid) : pid_(pid), read_redirect_func_(0) {} 104 virtual ~MemoryRemote() = default; 105 106 size_t Read(uint64_t addr, void* dst, size_t size) override; 107 pid()108 pid_t pid() { return pid_; } 109 110 private: 111 pid_t pid_; 112 std::atomic_uintptr_t read_redirect_func_; 113 }; 114 115 class MemoryLocal : public Memory { 116 public: 117 MemoryLocal() = default; 118 virtual ~MemoryLocal() = default; 119 120 size_t Read(uint64_t addr, void* dst, size_t size) override; 121 }; 122 123 // MemoryRange maps one address range onto another. 124 // The range [src_begin, src_begin + length) in the underlying Memory is mapped onto offset, 125 // such that range.read(offset) is equivalent to underlying.read(src_begin). 126 class MemoryRange : public Memory { 127 public: 128 MemoryRange(const std::shared_ptr<Memory>& memory, uint64_t begin, uint64_t length, 129 uint64_t offset); 130 virtual ~MemoryRange() = default; 131 132 size_t Read(uint64_t addr, void* dst, size_t size) override; 133 134 private: 135 std::shared_ptr<Memory> memory_; 136 uint64_t begin_; 137 uint64_t length_; 138 uint64_t offset_; 139 }; 140 141 class MemoryOffline : public Memory { 142 public: 143 MemoryOffline() = default; 144 virtual ~MemoryOffline() = default; 145 146 bool Init(const std::string& file, uint64_t offset); 147 148 size_t Read(uint64_t addr, void* dst, size_t size) override; 149 150 private: 151 std::unique_ptr<MemoryRange> memory_; 152 }; 153 154 class MemoryOfflineBuffer : public Memory { 155 public: 156 MemoryOfflineBuffer(const uint8_t* data, uint64_t start, uint64_t end); 157 virtual ~MemoryOfflineBuffer() = default; 158 159 void Reset(const uint8_t* data, uint64_t start, uint64_t end); 160 161 size_t Read(uint64_t addr, void* dst, size_t size) override; 162 163 private: 164 const uint8_t* data_; 165 uint64_t start_; 166 uint64_t end_; 167 }; 168 169 class MemoryOfflineParts : public Memory { 170 public: 171 MemoryOfflineParts() = default; 172 virtual ~MemoryOfflineParts(); 173 Add(MemoryOffline * memory)174 void Add(MemoryOffline* memory) { memories_.push_back(memory); } 175 176 size_t Read(uint64_t addr, void* dst, size_t size) override; 177 178 private: 179 std::vector<MemoryOffline*> memories_; 180 }; 181 182 } // namespace unwindstack 183 184 #endif // _LIBUNWINDSTACK_MEMORY_H 185