Skip to content

WIP: Sketch interpose-memreader command for lldb-test #1

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: swift/master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 58 additions & 0 deletions lldb/include/lldb/Target/SwiftRemoteMemoryReader.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
//===-- SwiftRemoteMemoryReader.h -------------------------------*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2020 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//

#ifndef liblldb_SwiftRemoteMemoryReader_h_
#define liblldb_SwiftRemoteMemoryReader_h_

#include "lldb/Target/Process.h"
#include "lldb/Target/SwiftLanguageRuntime.h"
#include "lldb/Target/Target.h"

#include "swift/Remote/MemoryReader.h"

namespace lldb_private {

/// Adapter class which allows the Swift Remote Mirrors library to reflect type
/// information from a remote process.
class LLDBMemoryReader : public swift::remote::MemoryReader {
public:
LLDBMemoryReader(Process &p, size_t max_read_amount = INT32_MAX);

virtual ~LLDBMemoryReader();

bool queryDataLayout(DataLayoutQueryType type, void *inBuffer,
void *outBuffer) override;

swift::remote::RemoteAddress
getSymbolAddress(const std::string &name) override;

bool readBytes(swift::remote::RemoteAddress address, uint8_t *dest,
uint64_t size) override;

bool readString(swift::remote::RemoteAddress address,
std::string &dest) override;

void pushLocalBuffer(uint64_t local_buffer, uint64_t local_buffer_size);

void popLocalBuffer();

private:
Process &m_process;
size_t m_max_read_amount;

uint64_t m_local_buffer = 0;
uint64_t m_local_buffer_size = 0;
};

} // namespace lldb_private

#endif // liblldb_SwiftRemoteMemoryReader_h_
1 change: 1 addition & 0 deletions lldb/source/Target/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ add_lldb_library(lldbTarget
SwiftLanguageRuntime.cpp
SwiftLanguageRuntimeDynamicTypeResolution.cpp
SwiftLanguageRuntimeNames.cpp
SwiftRemoteMemoryReader.cpp
SystemRuntime.cpp
Target.cpp
TargetList.cpp
Expand Down
208 changes: 1 addition & 207 deletions lldb/source/Target/SwiftLanguageRuntimeDynamicTypeResolution.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@

#include "SwiftLanguageRuntimeImpl.h"
#include "lldb/Target/SwiftLanguageRuntime.h"
#include "lldb/Target/SwiftRemoteMemoryReader.h"

#include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
#include "lldb/Symbol/Function.h"
Expand Down Expand Up @@ -266,213 +267,6 @@ const CompilerType &SwiftLanguageRuntimeImpl::GetBoxMetadataType() {
return m_box_metadata_type;
}

class LLDBMemoryReader : public swift::remote::MemoryReader {
public:
LLDBMemoryReader(Process &p, size_t max_read_amount = INT32_MAX)
: m_process(p) {
m_max_read_amount = max_read_amount;
}

virtual ~LLDBMemoryReader() = default;

bool queryDataLayout(DataLayoutQueryType type, void *inBuffer,
void *outBuffer) override {
switch (type) {
case DLQ_GetPointerSize: {
auto result = static_cast<uint8_t *>(outBuffer);
*result = m_process.GetAddressByteSize();
return true;
}
case DLQ_GetSizeSize: {
auto result = static_cast<uint8_t *>(outBuffer);
*result = m_process.GetAddressByteSize(); // FIXME: sizeof(size_t)
return true;
}
}

return false;
}

swift::remote::RemoteAddress
getSymbolAddress(const std::string &name) override {
lldbassert(!name.empty());
if (name.empty())
return swift::remote::RemoteAddress(nullptr);

LLDB_LOG(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES),
"[MemoryReader] asked to retrieve the address of symbol {0}",
name);

ConstString name_cs(name.c_str(), name.size());
SymbolContextList sc_list;
m_process.GetTarget().GetImages().FindSymbolsWithNameAndType(
name_cs, lldb::eSymbolTypeAny, sc_list);
if (!sc_list.GetSize()) {
LLDB_LOG(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES),
"[MemoryReader] symbol resolution failed {0}", name);
return swift::remote::RemoteAddress(nullptr);
}

SymbolContext sym_ctx;
// Remove undefined symbols from the list.
size_t num_sc_matches = sc_list.GetSize();
if (num_sc_matches > 1) {
SymbolContextList tmp_sc_list(sc_list);
sc_list.Clear();
for (size_t idx = 0; idx < num_sc_matches; idx++) {
tmp_sc_list.GetContextAtIndex(idx, sym_ctx);
if (sym_ctx.symbol &&
sym_ctx.symbol->GetType() != lldb::eSymbolTypeUndefined) {
sc_list.Append(sym_ctx);
}
}
}
if (sc_list.GetSize() == 1 && sc_list.GetContextAtIndex(0, sym_ctx)) {
if (sym_ctx.symbol) {
auto load_addr = sym_ctx.symbol->GetLoadAddress(&m_process.GetTarget());
LLDB_LOG(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES),
"[MemoryReader] symbol resolved to 0x%" PRIx64, load_addr);
return swift::remote::RemoteAddress(load_addr);
}
}

// Empty list, resolution failed.
if (sc_list.GetSize() == 0) {
LLDB_LOG(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES),
"[MemoryReader] symbol resoution failed {0}", name);
return swift::remote::RemoteAddress(nullptr);
}

// If there's a single symbol, then we're golden. If there's more than
// a symbol, then just make sure all of them agree on the value.
Status error;
auto sym = sc_list.GetContextAtIndex(0, sym_ctx);
auto load_addr = sym_ctx.symbol->GetLoadAddress(&m_process.GetTarget());
uint64_t sym_value = m_process.GetTarget().ReadUnsignedIntegerFromMemory(
load_addr, false, m_process.GetAddressByteSize(), 0, error);
for (unsigned i = 1; i < sc_list.GetSize(); ++i) {
auto other_sym = sc_list.GetContextAtIndex(i, sym_ctx);
auto other_load_addr =
sym_ctx.symbol->GetLoadAddress(&m_process.GetTarget());
uint64_t other_sym_value =
m_process.GetTarget().ReadUnsignedIntegerFromMemory(
load_addr, false, m_process.GetAddressByteSize(), 0, error);
if (sym_value != other_sym_value) {
LLDB_LOG(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES),
"[MemoryReader] symbol resoution failed {0}", name);
return swift::remote::RemoteAddress(nullptr);
}
}
LLDB_LOG(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES),
"[MemoryReader] symbol resolved to {0}", load_addr);
return swift::remote::RemoteAddress(load_addr);
}

bool readBytes(swift::remote::RemoteAddress address, uint8_t *dest,
uint64_t size) override {
if (m_local_buffer) {
auto addr = address.getAddressData();
if (addr >= m_local_buffer &&
addr + size <= m_local_buffer + m_local_buffer_size) {
// If this crashes, the assumptions stated in
// GetDynamicTypeAndAddress_Protocol() most likely no longer
// hold.
memcpy(dest, (void *)addr, size);
return true;
}
}

Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES));

if (log)
log->Printf("[MemoryReader] asked to read %" PRIu64
" bytes at address 0x%" PRIx64,
size, address.getAddressData());

if (size > m_max_read_amount) {
if (log)
log->Printf("[MemoryReader] memory read exceeds maximum allowed size");
return false;
}

Target &target(m_process.GetTarget());
Address addr(address.getAddressData());
Status error;
if (size > target.ReadMemory(addr, false, dest, size, error)) {
if (log)
log->Printf(
"[MemoryReader] memory read returned fewer bytes than asked for");
return false;
}
if (error.Fail()) {
if (log)
log->Printf("[MemoryReader] memory read returned error: %s",
error.AsCString());
return false;
}

if (log && log->GetVerbose()) {
StreamString stream;
for (uint64_t i = 0; i < size; i++) {
stream.PutHex8(dest[i]);
stream.PutChar(' ');
}
log->Printf("[MemoryReader] memory read returned data: %s",
stream.GetData());
}

return true;
}

bool readString(swift::remote::RemoteAddress address,
std::string &dest) override {
Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES));

if (log)
log->Printf(
"[MemoryReader] asked to read string data at address 0x%" PRIx64,
address.getAddressData());

uint32_t read_size = 50 * 1024;
std::vector<char> storage(read_size, 0);
Target &target(m_process.GetTarget());
Address addr(address.getAddressData());
Status error;
target.ReadCStringFromMemory(addr, &storage[0], storage.size(), error);
if (error.Success()) {
dest.assign(&storage[0]);
if (log)
log->Printf("[MemoryReader] memory read returned data: %s",
dest.c_str());
return true;
} else {
if (log)
log->Printf("[MemoryReader] memory read returned error: %s",
error.AsCString());
return false;
}
}

void pushLocalBuffer(uint64_t local_buffer, uint64_t local_buffer_size) {
lldbassert(!m_local_buffer);
m_local_buffer = local_buffer;
m_local_buffer_size = local_buffer_size;
}

void popLocalBuffer() {
lldbassert(m_local_buffer);
m_local_buffer = 0;
m_local_buffer_size = 0;
}

private:
Process &m_process;
size_t m_max_read_amount;

uint64_t m_local_buffer = 0;
uint64_t m_local_buffer_size = 0;
};

std::shared_ptr<swift::remote::MemoryReader>
SwiftLanguageRuntimeImpl::GetMemoryReader() {
if (!m_memory_reader_sp)
Expand Down
Loading