Skip to content

Commit 455ce1c

Browse files
authored
[lldb] Fix local buffer not being popped (#10718)
On a recent change in GetDynamicTypeAndAddress_Existential, the local buffer was being pushed but never popped. This fixes the issue by introducing a new RAII data structure that will pop the local buffer when out of scope. rdar://148137949
1 parent e3d5fc0 commit 455ce1c

File tree

8 files changed

+178
-96
lines changed

8 files changed

+178
-96
lines changed

lldb/source/Plugins/LanguageRuntime/Swift/LLDBMemoryReader.cpp

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@
1616
#include "lldb/Utility/LLDBLog.h"
1717
#include "lldb/Utility/Log.h"
1818

19-
#include "llvm/Support/MathExtras.h"
2019
#include "swift/Demangling/Demangle.h"
20+
#include "llvm/Support/MathExtras.h"
2121

2222
using namespace lldb;
2323
using namespace lldb_private;
@@ -275,8 +275,7 @@ LLDBMemoryReader::resolvePointer(swift::remote::RemoteAddress address,
275275

276276
auto *section_list = module_containing_pointer->GetSectionList();
277277
if (section_list->GetSize() == 0) {
278-
LLDB_LOG(log,
279-
"[MemoryReader] Module with empty section list.");
278+
LLDB_LOG(log, "[MemoryReader] Module with empty section list.");
280279
return {};
281280
}
282281

@@ -452,11 +451,18 @@ bool LLDBMemoryReader::readString(swift::remote::RemoteAddress address,
452451
return false;
453452
}
454453

455-
void LLDBMemoryReader::pushLocalBuffer(uint64_t local_buffer,
456-
uint64_t local_buffer_size) {
454+
MemoryReaderLocalBufferHolder::~MemoryReaderLocalBufferHolder() {
455+
if (m_memory_reader)
456+
m_memory_reader->popLocalBuffer();
457+
}
458+
459+
MemoryReaderLocalBufferHolder
460+
LLDBMemoryReader::pushLocalBuffer(uint64_t local_buffer,
461+
uint64_t local_buffer_size) {
457462
lldbassert(!m_local_buffer);
458463
m_local_buffer = local_buffer;
459464
m_local_buffer_size = local_buffer_size;
465+
return MemoryReaderLocalBufferHolder(this);
460466
}
461467

462468
void LLDBMemoryReader::popLocalBuffer() {
@@ -579,8 +585,7 @@ LLDBMemoryReader::getFileAddressAndModuleForTaggedAddress(
579585
ModuleSP module = pair_iterator->second;
580586
auto *section_list = module->GetSectionList();
581587
if (section_list->GetSize() == 0) {
582-
LLDB_LOG(log,
583-
"[MemoryReader] Module with empty section list.");
588+
LLDB_LOG(log, "[MemoryReader] Module with empty section list.");
584589
return {};
585590
}
586591
uint64_t file_address;
@@ -620,8 +625,8 @@ LLDBMemoryReader::resolveRemoteAddress(uint64_t address) const {
620625
Address resolved(file_address, object_file->GetSectionList());
621626

622627
// If the address doesn't have a section it means we couldn't find a section
623-
// that contains that file address, and the "resolved" instance is wrong.
624-
// Calculate the virtual address by finding out the slide of the associated
628+
// that contains that file address, and the "resolved" instance is wrong.
629+
// Calculate the virtual address by finding out the slide of the associated
625630
// module, and adding that to the file address.
626631
if (resolved.GetSection()) {
627632
LLDB_LOGV(log,

lldb/source/Plugins/LanguageRuntime/Swift/LLDBMemoryReader.h

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,35 @@
2424
#include "llvm/Support/Memory.h"
2525

2626
namespace lldb_private {
27+
class LLDBMemoryReader;
28+
class MemoryReaderLocalBufferHolder {
29+
public:
30+
MemoryReaderLocalBufferHolder() : m_memory_reader(nullptr) {}
31+
MemoryReaderLocalBufferHolder(MemoryReaderLocalBufferHolder &&other)
32+
: m_memory_reader(other.m_memory_reader) {
33+
other.m_memory_reader = nullptr;
34+
}
35+
36+
MemoryReaderLocalBufferHolder &operator=(MemoryReaderLocalBufferHolder &&other) {
37+
this->m_memory_reader = other.m_memory_reader;
38+
other.m_memory_reader = nullptr;
39+
return *this;
40+
}
41+
42+
~MemoryReaderLocalBufferHolder();
43+
private:
44+
friend LLDBMemoryReader;
45+
46+
MemoryReaderLocalBufferHolder(LLDBMemoryReader *memory_reader)
47+
: m_memory_reader(memory_reader) {}
48+
49+
LLDBMemoryReader *m_memory_reader;
50+
};
51+
2752
class LLDBMemoryReader : public swift::remote::MemoryReader {
2853
public:
54+
55+
2956
LLDBMemoryReader(Process &p,
3057
std::function<swift::remote::RemoteAbsolutePointer(
3158
swift::remote::RemoteAbsolutePointer)>
@@ -56,9 +83,7 @@ class LLDBMemoryReader : public swift::remote::MemoryReader {
5683
bool readString(swift::remote::RemoteAddress address,
5784
std::string &dest) override;
5885

59-
void pushLocalBuffer(uint64_t local_buffer, uint64_t local_buffer_size);
60-
61-
void popLocalBuffer();
86+
MemoryReaderLocalBufferHolder pushLocalBuffer(uint64_t local_buffer, uint64_t local_buffer_size);
6287

6388
/// Adds the module to the list of modules we're tracking using tagged
6489
/// addresses, so we can read memory from the file cache whenever possible.
@@ -71,6 +96,10 @@ class LLDBMemoryReader : public swift::remote::MemoryReader {
7196
bool readMetadataFromFileCacheEnabled() const;
7297

7398
private:
99+
friend MemoryReaderLocalBufferHolder;
100+
101+
void popLocalBuffer();
102+
74103
/// Gets the file address and module that were mapped to a given tagged
75104
/// address.
76105
std::optional<std::pair<uint64_t, lldb::ModuleSP>>

lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntime.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ class SwiftLanguageRuntimeStub;
6363
class SwiftLanguageRuntimeImpl;
6464
class ReflectionContextInterface;
6565
class LLDBMemoryReader;
66+
class MemoryReaderLocalBufferHolder;
6667
struct SuperClassType;
6768

6869
using ThreadSafeReflectionContext = LockGuarded<ReflectionContextInterface>;
@@ -726,9 +727,8 @@ class SwiftLanguageRuntime : public LanguageRuntime {
726727

727728
std::shared_ptr<LLDBMemoryReader> GetMemoryReader();
728729

729-
void PushLocalBuffer(uint64_t local_buffer, uint64_t local_buffer_size);
730-
731-
void PopLocalBuffer();
730+
MemoryReaderLocalBufferHolder PushLocalBuffer(uint64_t local_buffer,
731+
uint64_t local_buffer_size);
732732

733733
// These are the helper functions for GetObjectDescription for various
734734
// types of swift objects.

lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeDynamicTypeResolution.cpp

Lines changed: 75 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -260,15 +260,12 @@ std::shared_ptr<LLDBMemoryReader> SwiftLanguageRuntime::GetMemoryReader() {
260260
return m_memory_reader_sp;
261261
}
262262

263-
void SwiftLanguageRuntime::PushLocalBuffer(uint64_t local_buffer,
263+
MemoryReaderLocalBufferHolder SwiftLanguageRuntime::PushLocalBuffer(uint64_t local_buffer,
264264
uint64_t local_buffer_size) {
265-
((LLDBMemoryReader *)GetMemoryReader().get())
265+
return ((LLDBMemoryReader *)GetMemoryReader().get())
266266
->pushLocalBuffer(local_buffer, local_buffer_size);
267267
}
268268

269-
void SwiftLanguageRuntime::PopLocalBuffer() {
270-
((LLDBMemoryReader *)GetMemoryReader().get())->popLocalBuffer();
271-
}
272269

273270
class LLDBTypeInfoProvider : public swift::remote::TypeInfoProvider {
274271
SwiftLanguageRuntime &m_runtime;
@@ -1599,8 +1596,7 @@ llvm::Expected<std::string> SwiftLanguageRuntime::GetEnumCaseName(
15991596
return "";
16001597

16011598
auto *eti = llvm::cast<EnumTypeInfo>(ti);
1602-
PushLocalBuffer((int64_t)data.GetDataStart(), data.GetByteSize());
1603-
auto defer = llvm::make_scope_exit([&] { PopLocalBuffer(); });
1599+
auto buffer_holder = PushLocalBuffer((int64_t)data.GetDataStart(), data.GetByteSize());
16041600
RemoteAddress addr(data.GetDataStart());
16051601
int case_index;
16061602
if (eti->projectEnumValue(*GetMemoryReader(), addr, &case_index))
@@ -2313,85 +2309,87 @@ bool SwiftLanguageRuntime::GetDynamicTypeAndAddress_Existential(
23132309
return false;
23142310
}
23152311

2312+
// This scope is needed because the validation code will call PushLocalBuffer,
2313+
// so we need to pop it before that call.
2314+
{
2315+
MemoryReaderLocalBufferHolder holder;
2316+
if (use_local_buffer)
2317+
holder = PushLocalBuffer(
2318+
existential_address,
2319+
llvm::expectedToOptional(in_value.GetByteSize()).value_or(0));
23162320

2317-
if (use_local_buffer)
2318-
PushLocalBuffer(
2319-
existential_address,
2320-
llvm::expectedToOptional(in_value.GetByteSize()).value_or(0));
2321-
2322-
swift::remote::RemoteAddress remote_existential(existential_address);
2323-
2324-
ThreadSafeReflectionContext reflection_ctx = GetReflectionContext();
2325-
if (!reflection_ctx)
2326-
return false;
2327-
auto tr_ts = tss->GetTypeSystemSwiftTypeRef();
2328-
if (!tr_ts)
2329-
return false;
2330-
2331-
auto flavor = SwiftLanguageRuntime::GetManglingFlavor(
2332-
existential_type.GetMangledTypeName());
2333-
CompilerType dynamic_type;
2334-
uint64_t dynamic_address = 0;
2335-
if (flavor == swift::Mangle::ManglingFlavor::Default) {
2336-
auto pair = reflection_ctx->ProjectExistentialAndUnwrapClass(
2337-
remote_existential, *existential_typeref, tr_ts->GetDescriptorFinder());
2338-
2339-
if (!pair) {
2340-
if (log)
2341-
log->Printf("Runtime failed to get dynamic type of existential");
2342-
return false;
2343-
}
2344-
2345-
const swift::reflection::TypeRef *typeref;
2346-
swift::remote::RemoteAddress out_address(nullptr);
2347-
std::tie(typeref, out_address) = *pair;
2321+
swift::remote::RemoteAddress remote_existential(existential_address);
23482322

2349-
auto ts = tss->GetTypeSystemSwiftTypeRef();
2350-
if (!ts)
2351-
return false;
2352-
swift::Demangle::Demangler dem;
2353-
swift::Demangle::NodePointer node = typeref->getDemangling(dem);
2354-
dynamic_type = ts->RemangleAsType(dem, node, flavor);
2355-
dynamic_address = out_address.getAddressData();
2356-
} else {
2357-
// In the embedded Swift case, the existential container just points to the
2358-
// instance.
2359-
auto reflection_ctx = GetReflectionContext();
2323+
ThreadSafeReflectionContext reflection_ctx = GetReflectionContext();
23602324
if (!reflection_ctx)
23612325
return false;
2362-
auto maybe_addr_or_symbol =
2363-
reflection_ctx->ReadPointer(existential_address);
2364-
if (!maybe_addr_or_symbol)
2326+
auto tr_ts = tss->GetTypeSystemSwiftTypeRef();
2327+
if (!tr_ts)
23652328
return false;
23662329

2367-
uint64_t address = 0;
2368-
if (maybe_addr_or_symbol->isResolved()) {
2369-
address = maybe_addr_or_symbol->getOffset();
2330+
auto flavor = SwiftLanguageRuntime::GetManglingFlavor(
2331+
existential_type.GetMangledTypeName());
2332+
CompilerType dynamic_type;
2333+
uint64_t dynamic_address = 0;
2334+
if (flavor == swift::Mangle::ManglingFlavor::Default) {
2335+
auto pair = reflection_ctx->ProjectExistentialAndUnwrapClass(
2336+
remote_existential, *existential_typeref,
2337+
tr_ts->GetDescriptorFinder());
2338+
2339+
if (!pair) {
2340+
if (log)
2341+
log->Printf("Runtime failed to get dynamic type of existential");
2342+
return false;
2343+
}
2344+
2345+
const swift::reflection::TypeRef *typeref;
2346+
swift::remote::RemoteAddress out_address(nullptr);
2347+
std::tie(typeref, out_address) = *pair;
2348+
2349+
auto ts = tss->GetTypeSystemSwiftTypeRef();
2350+
if (!ts)
2351+
return false;
2352+
swift::Demangle::Demangler dem;
2353+
swift::Demangle::NodePointer node = typeref->getDemangling(dem);
2354+
dynamic_type = ts->RemangleAsType(dem, node, flavor);
2355+
dynamic_address = out_address.getAddressData();
23702356
} else {
2371-
SymbolContextList sc_list;
2372-
auto &module_list = GetProcess().GetTarget().GetImages();
2373-
module_list.FindSymbolsWithNameAndType(
2374-
ConstString(maybe_addr_or_symbol->getSymbol()), eSymbolTypeAny,
2375-
sc_list);
2376-
if (sc_list.GetSize() != 1)
2357+
// In the embedded Swift case, the existential container just points to
2358+
// the instance.
2359+
auto reflection_ctx = GetReflectionContext();
2360+
if (!reflection_ctx)
2361+
return false;
2362+
auto maybe_addr_or_symbol =
2363+
reflection_ctx->ReadPointer(existential_address);
2364+
if (!maybe_addr_or_symbol)
23772365
return false;
23782366

2379-
SymbolContext sc = sc_list[0];
2380-
Symbol *symbol = sc.symbol;
2381-
address = symbol->GetLoadAddress(&GetProcess().GetTarget());
2382-
}
2367+
uint64_t address = 0;
2368+
if (maybe_addr_or_symbol->isResolved()) {
2369+
address = maybe_addr_or_symbol->getOffset();
2370+
} else {
2371+
SymbolContextList sc_list;
2372+
auto &module_list = GetProcess().GetTarget().GetImages();
2373+
module_list.FindSymbolsWithNameAndType(
2374+
ConstString(maybe_addr_or_symbol->getSymbol()), eSymbolTypeAny,
2375+
sc_list);
2376+
if (sc_list.GetSize() != 1)
2377+
return false;
2378+
2379+
SymbolContext sc = sc_list[0];
2380+
Symbol *symbol = sc.symbol;
2381+
address = symbol->GetLoadAddress(&GetProcess().GetTarget());
2382+
}
23832383

2384-
dynamic_type =
2385-
GetDynamicTypeAndAddress_EmbeddedClass(address, existential_type);
2386-
if (!dynamic_type)
2387-
return false;
2388-
dynamic_address = maybe_addr_or_symbol->getOffset();
2384+
dynamic_type =
2385+
GetDynamicTypeAndAddress_EmbeddedClass(address, existential_type);
2386+
if (!dynamic_type)
2387+
return false;
2388+
dynamic_address = maybe_addr_or_symbol->getOffset();
2389+
}
2390+
class_type_or_name.SetCompilerType(dynamic_type);
2391+
address.SetRawAddress(dynamic_address);
23892392
}
2390-
if (use_local_buffer)
2391-
PopLocalBuffer();
2392-
2393-
class_type_or_name.SetCompilerType(dynamic_type);
2394-
address.SetRawAddress(dynamic_address);
23952393

23962394
#ifndef NDEBUG
23972395
if (ModuleList::GetGlobalModuleListProperties()
@@ -2893,8 +2891,9 @@ Value::ValueType SwiftLanguageRuntime::GetValueType(
28932891
existential_address = in_value.GetAddressOf();
28942892
}
28952893

2894+
MemoryReaderLocalBufferHolder holder;
28962895
if (use_local_buffer)
2897-
PushLocalBuffer(
2896+
holder = PushLocalBuffer(
28982897
existential_address,
28992898
llvm::expectedToOptional(in_value.GetByteSize()).value_or(0));
29002899

@@ -2906,8 +2905,6 @@ Value::ValueType SwiftLanguageRuntime::GetValueType(
29062905
reflection_ctx->IsValueInlinedInExistentialContainer(
29072906
remote_existential);
29082907

2909-
if (use_local_buffer)
2910-
PopLocalBuffer();
29112908

29122909
// An error has occurred when trying to read value witness table,
29132910
// default to treating it as pointer.

lldb/source/Plugins/LanguageRuntime/Swift/SwiftLanguageRuntimeRemoteAST.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -246,15 +246,14 @@ SwiftLanguageRuntime::GetDynamicTypeAndAddress_ExistentialRemoteAST(
246246
.value_or(swift::Type());
247247
if (!swift_type)
248248
return {};
249+
MemoryReaderLocalBufferHolder holder;
249250
if (use_local_buffer)
250-
PushLocalBuffer(
251+
holder = PushLocalBuffer(
251252
existential_address,
252253
llvm::expectedToOptional(in_value.GetByteSize()).value_or(0));
253254

254255
auto result = remote_ast.getDynamicTypeAndAddressForExistential(
255256
remote_existential, swift_type);
256-
if (use_local_buffer)
257-
PopLocalBuffer();
258257

259258
if (!result.isSuccess())
260259
return {};
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
SWIFT_SOURCES := main.swift
2+
3+
include Makefile.rules
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import lldb
2+
from lldbsuite.test.lldbtest import *
3+
from lldbsuite.test.decorators import *
4+
import lldbsuite.test.lldbutil as lldbutil
5+
import os
6+
7+
8+
class TestSwiftOriginallyDefinedInPayload(TestBase):
9+
@swiftTest
10+
def test(self):
11+
self.build()
12+
13+
# rdar://151579199
14+
self.runCmd("setting set symbols.swift-validate-typesystem false")
15+
16+
lldbutil.run_to_source_breakpoint(
17+
self, "break here", lldb.SBFileSpec("main.swift")
18+
)
19+
20+
self.expect(
21+
"frame variable c",
22+
substrs=[
23+
"c = 1 value",
24+
"flexible = {",
25+
"0 = (value = 100)",
26+
"1 = (value = 200)",
27+
" 2 = (value = 300)",
28+
],
29+
)

0 commit comments

Comments
 (0)