Skip to content

Commit 0d7fbd0

Browse files
authored
Merge pull request #3825 from augusto2112/move-lldb-memory-reader-next
[lldb] Move LLDBMemoryReader to its own file
2 parents 55fda8b + 9c3fbd0 commit 0d7fbd0

File tree

4 files changed

+263
-223
lines changed

4 files changed

+263
-223
lines changed

lldb/source/Plugins/LanguageRuntime/Swift/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
add_lldb_library(lldbPluginSwiftLanguageRuntime PLUGIN
2+
LLDBMemoryReader.cpp
23
SwiftLanguageRuntime.cpp
34
SwiftLanguageRuntimeDynamicTypeResolution.cpp
45
SwiftLanguageRuntimeNames.cpp
Lines changed: 217 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,217 @@
1+
#include "LLDBMemoryReader.h"
2+
#include "lldb/Core/Section.h"
3+
#include "lldb/Utility/Log.h"
4+
#include "lldb/Utility/Logging.h"
5+
6+
using namespace lldb;
7+
using namespace lldb_private;
8+
9+
namespace lldb_private {
10+
bool LLDBMemoryReader::queryDataLayout(DataLayoutQueryType type, void *inBuffer,
11+
void *outBuffer) {
12+
switch (type) {
13+
// FIXME: add support for case DLQ_GetPtrAuthMask rdar://70729149
14+
case DLQ_GetPtrAuthMask:
15+
return false;
16+
case DLQ_GetObjCReservedLowBits: {
17+
auto *result = static_cast<uint8_t *>(outBuffer);
18+
auto &triple = m_process.GetTarget().GetArchitecture().GetTriple();
19+
if (triple.isMacOSX() && triple.getArch() == llvm::Triple::x86_64) {
20+
// Obj-C reserves low bit on 64-bit Intel macOS only.
21+
// Other Apple platforms don't reserve this bit (even when
22+
// running on x86_64-based simulators).
23+
*result = 1;
24+
} else {
25+
*result = 0;
26+
}
27+
return true;
28+
}
29+
case DLQ_GetPointerSize: {
30+
auto *result = static_cast<uint8_t *>(outBuffer);
31+
*result = m_process.GetAddressByteSize();
32+
return true;
33+
}
34+
case DLQ_GetSizeSize: {
35+
auto *result = static_cast<uint8_t *>(outBuffer);
36+
*result = m_process.GetAddressByteSize(); // FIXME: sizeof(size_t)
37+
return true;
38+
}
39+
case DLQ_GetLeastValidPointerValue: {
40+
auto *result = (uint64_t *)outBuffer;
41+
auto &triple = m_process.GetTarget().GetArchitecture().GetTriple();
42+
if (triple.isOSDarwin() && triple.isArch64Bit())
43+
*result = 0x100000000;
44+
else
45+
*result = 0x1000;
46+
return true;
47+
}
48+
}
49+
}
50+
51+
swift::remote::RemoteAddress
52+
LLDBMemoryReader::getSymbolAddress(const std::string &name) {
53+
lldbassert(!name.empty());
54+
if (name.empty())
55+
return swift::remote::RemoteAddress(nullptr);
56+
57+
Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES));
58+
59+
LLDB_LOGV(log, "[MemoryReader] asked to retrieve the address of symbol {0}",
60+
name);
61+
62+
ConstString name_cs(name.c_str(), name.size());
63+
SymbolContextList sc_list;
64+
m_process.GetTarget().GetImages().FindSymbolsWithNameAndType(
65+
name_cs, lldb::eSymbolTypeAny, sc_list);
66+
if (!sc_list.GetSize()) {
67+
LLDB_LOGV(log, "[MemoryReader] symbol resolution failed {0}", name);
68+
return swift::remote::RemoteAddress(nullptr);
69+
}
70+
71+
SymbolContext sym_ctx;
72+
// Remove undefined symbols from the list.
73+
size_t num_sc_matches = sc_list.GetSize();
74+
if (num_sc_matches > 1) {
75+
SymbolContextList tmp_sc_list(sc_list);
76+
sc_list.Clear();
77+
for (size_t idx = 0; idx < num_sc_matches; idx++) {
78+
tmp_sc_list.GetContextAtIndex(idx, sym_ctx);
79+
if (sym_ctx.symbol &&
80+
sym_ctx.symbol->GetType() != lldb::eSymbolTypeUndefined) {
81+
sc_list.Append(sym_ctx);
82+
}
83+
}
84+
}
85+
if (sc_list.GetSize() == 1 && sc_list.GetContextAtIndex(0, sym_ctx)) {
86+
if (sym_ctx.symbol) {
87+
auto load_addr = sym_ctx.symbol->GetLoadAddress(&m_process.GetTarget());
88+
LLDB_LOGV(log, "[MemoryReader] symbol resolved to {0:x}", load_addr);
89+
return swift::remote::RemoteAddress(load_addr);
90+
}
91+
}
92+
93+
// Empty list, resolution failed.
94+
if (sc_list.GetSize() == 0) {
95+
LLDB_LOGV(log, "[MemoryReader] symbol resolution failed {0}", name);
96+
return swift::remote::RemoteAddress(nullptr);
97+
}
98+
99+
// If there's a single symbol, then we're golden. If there's more than
100+
// a symbol, then just make sure all of them agree on the value.
101+
Status error;
102+
auto load_addr = sym_ctx.symbol->GetLoadAddress(&m_process.GetTarget());
103+
uint64_t sym_value = m_process.GetTarget().ReadUnsignedIntegerFromMemory(
104+
load_addr, m_process.GetAddressByteSize(), 0, error, true);
105+
for (unsigned i = 1; i < sc_list.GetSize(); ++i) {
106+
uint64_t other_sym_value =
107+
m_process.GetTarget().ReadUnsignedIntegerFromMemory(
108+
load_addr, m_process.GetAddressByteSize(), 0, error, true);
109+
if (sym_value != other_sym_value) {
110+
LLDB_LOGV(log, "[MemoryReader] symbol resolution failed {0}", name);
111+
return swift::remote::RemoteAddress(nullptr);
112+
}
113+
}
114+
LLDB_LOGV(log, "[MemoryReader] symbol resolved to {0}", load_addr);
115+
return swift::remote::RemoteAddress(load_addr);
116+
}
117+
118+
bool LLDBMemoryReader::readBytes(swift::remote::RemoteAddress address,
119+
uint8_t *dest, uint64_t size) {
120+
if (m_local_buffer) {
121+
auto addr = address.getAddressData();
122+
if (addr >= *m_local_buffer &&
123+
addr + size <= *m_local_buffer + m_local_buffer_size) {
124+
// If this crashes, the assumptions stated in
125+
// GetDynamicTypeAndAddress_Protocol() most likely no longer
126+
// hold.
127+
memcpy(dest, (void *)addr, size);
128+
return true;
129+
}
130+
}
131+
132+
Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES));
133+
134+
LLDB_LOGV(log, "[MemoryReader] asked to read {0} bytes at address {1:x}",
135+
size, address.getAddressData());
136+
137+
if (size > m_max_read_amount) {
138+
LLDB_LOGV(log, "[MemoryReader] memory read exceeds maximum allowed size");
139+
return false;
140+
}
141+
142+
Target &target(m_process.GetTarget());
143+
Address addr(address.getAddressData());
144+
Status error;
145+
if (size > target.ReadMemory(addr, dest, size, error, true)) {
146+
LLDB_LOGV(log,
147+
"[MemoryReader] memory read returned fewer bytes than asked for");
148+
return false;
149+
}
150+
if (error.Fail()) {
151+
LLDB_LOGV(log, "[MemoryReader] memory read returned error: {0}",
152+
error.AsCString());
153+
return false;
154+
}
155+
156+
auto format_data = [](auto dest, auto size) {
157+
StreamString stream;
158+
for (uint64_t i = 0; i < size; i++) {
159+
stream.PutHex8(dest[i]);
160+
stream.PutChar(' ');
161+
}
162+
return stream.GetData();
163+
};
164+
LLDB_LOGV(log, "[MemoryReader] memory read returned data: {0}",
165+
format_data(dest, size));
166+
167+
return true;
168+
}
169+
170+
bool LLDBMemoryReader::readString(swift::remote::RemoteAddress address,
171+
std::string &dest) {
172+
Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES));
173+
174+
LLDB_LOGV(log, "[MemoryReader] asked to read string data at address {0:x}",
175+
address.getAddressData());
176+
177+
Target &target(m_process.GetTarget());
178+
Address addr(address.getAddressData());
179+
Status error;
180+
target.ReadCStringFromMemory(addr, dest, error);
181+
if (error.Success()) {
182+
auto format_string = [](const std::string &dest) {
183+
StreamString stream;
184+
for (auto c : dest) {
185+
if (c >= 32 && c <= 127) {
186+
stream << c;
187+
} else {
188+
stream << "\\0";
189+
stream.PutHex8(c);
190+
}
191+
}
192+
return stream.GetData();
193+
};
194+
LLDB_LOGV(log, "[MemoryReader] memory read returned data: \"{0}\"",
195+
format_string(dest));
196+
return true;
197+
} else {
198+
LLDB_LOGV(log, "[MemoryReader] memory read returned error: {0}",
199+
error.AsCString());
200+
return false;
201+
}
202+
}
203+
204+
void LLDBMemoryReader::pushLocalBuffer(uint64_t local_buffer,
205+
uint64_t local_buffer_size) {
206+
lldbassert(!m_local_buffer);
207+
m_local_buffer = local_buffer;
208+
m_local_buffer_size = local_buffer_size;
209+
}
210+
211+
void LLDBMemoryReader::popLocalBuffer() {
212+
lldbassert(m_local_buffer);
213+
m_local_buffer.reset();
214+
m_local_buffer_size = 0;
215+
}
216+
217+
} // namespace lldb_private
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
2+
#ifndef liblldb_LLDBMemoryReader_h_
3+
#define liblldb_LLDBMemoryReader_h_
4+
5+
#include "SwiftLanguageRuntime.h"
6+
#include "swift/Reflection/TypeLowering.h"
7+
#include "llvm/Support/Memory.h"
8+
9+
10+
namespace lldb_private {
11+
class LLDBMemoryReader : public swift::remote::MemoryReader {
12+
public:
13+
LLDBMemoryReader(Process &p, size_t max_read_amount = INT32_MAX)
14+
: m_process(p) {
15+
m_max_read_amount = max_read_amount;
16+
}
17+
18+
virtual ~LLDBMemoryReader() = default;
19+
20+
bool queryDataLayout(DataLayoutQueryType type, void *inBuffer,
21+
void *outBuffer) override;
22+
23+
swift::remote::RemoteAddress
24+
getSymbolAddress(const std::string &name) override;
25+
26+
bool readBytes(swift::remote::RemoteAddress address, uint8_t *dest,
27+
uint64_t size) override;
28+
29+
bool readString(swift::remote::RemoteAddress address,
30+
std::string &dest) override;
31+
32+
void pushLocalBuffer(uint64_t local_buffer, uint64_t local_buffer_size);
33+
34+
void popLocalBuffer();
35+
36+
private:
37+
Process &m_process;
38+
size_t m_max_read_amount;
39+
40+
llvm::Optional<uint64_t> m_local_buffer;
41+
uint64_t m_local_buffer_size = 0;
42+
};
43+
} // namespace lldb_private
44+
#endif

0 commit comments

Comments
 (0)