Skip to content

Commit 6eaedbb

Browse files
committed
Make CompilerType safe
When a process gets restarted TypeSystem objects associated with it may get deleted, and any CompilerType objects holding on to a reference to that type system are a use-after-free in waiting. Because of the SBAPI, we don't have tight control over where CompilerTypes go and when they are used. This is particularly a problem in the Swift plugin, where the scratch TypeSystem can be restarted while the process is still running. The Swift plugin has a lock to prevent abuse, but where there's a lock there can be bugs. This patch changes CompilerType to store a std::weak_ptr<TypeSystem>. Most of the std::weak_ptr<TypeSystem>* uglyness is hidden by introducing a wrapper class CompilerType::WrappedTypeSystem that has a dyn_cast_or_null() method. The only sites that need to know about the weak pointer implementation detail are the ones that deal with creating TypeSystems. rdar://101505232 Differential Revision: https://reviews.llvm.org/D136650
1 parent 0fcb26c commit 6eaedbb

File tree

83 files changed

+1052
-662
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

83 files changed

+1052
-662
lines changed

lldb/include/lldb/Core/Module.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -812,10 +812,10 @@ class Module : public std::enable_shared_from_this<Module>,
812812

813813
bool GetIsDynamicLinkEditor();
814814

815-
llvm::Expected<TypeSystem &>
815+
llvm::Expected<lldb::TypeSystemSP>
816816
GetTypeSystemForLanguage(lldb::LanguageType language);
817817

818-
void ForEachTypeSystem(llvm::function_ref<bool(TypeSystem *)> callback);
818+
void ForEachTypeSystem(llvm::function_ref<bool(lldb::TypeSystemSP)> callback);
819819

820820
// Special error functions that can do printf style formatting that will
821821
// prepend the message with something appropriate for this module (like the

lldb/include/lldb/Symbol/CompilerType.h

Lines changed: 68 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,12 @@
1515

1616
#include "lldb/lldb-private.h"
1717
#include "llvm/ADT/APSInt.h"
18+
#include "llvm/Support/Casting.h"
1819

1920
namespace lldb_private {
2021

2122
class DataExtractor;
23+
class TypeSystem;
2224

2325
/// Generic representation of a type in a programming language.
2426
///
@@ -38,38 +40,87 @@ class CompilerType {
3840
/// implementation.
3941
///
4042
/// \see lldb_private::TypeSystemClang::GetType(clang::QualType)
41-
CompilerType(TypeSystem *type_system, lldb::opaque_compiler_type_t type)
42-
: m_type(type), m_type_system(type_system) {
43+
CompilerType(lldb::TypeSystemWP type_system,
44+
lldb::opaque_compiler_type_t type)
45+
: m_type_system(type_system), m_type(type) {
46+
assert(Verify() && "verification failed");
47+
}
48+
49+
/// This is a minimal wrapper of a TypeSystem shared pointer as
50+
/// returned by CompilerType which conventien dyn_cast support.
51+
class TypeSystemSPWrapper {
52+
lldb::TypeSystemSP m_typesystem_sp;
53+
54+
public:
55+
TypeSystemSPWrapper() = default;
56+
TypeSystemSPWrapper(lldb::TypeSystemSP typesystem_sp)
57+
: m_typesystem_sp(typesystem_sp) {}
58+
59+
template <class TypeSystemType> bool isa_and_nonnull() {
60+
if (auto *ts = m_typesystem_sp.get())
61+
return llvm::isa<TypeSystemType>(ts);
62+
return false;
63+
}
64+
65+
/// Return a shared_ptr<TypeSystemType> if dyn_cast succeeds.
66+
template <class TypeSystemType>
67+
std::shared_ptr<TypeSystemType> dyn_cast_or_null() {
68+
if (isa_and_nonnull<TypeSystemType>())
69+
return std::shared_ptr<TypeSystemType>(
70+
m_typesystem_sp, llvm::cast<TypeSystemType>(m_typesystem_sp.get()));
71+
return nullptr;
72+
}
73+
74+
explicit operator bool() const {
75+
return static_cast<bool>(m_typesystem_sp);
76+
}
77+
bool operator==(const TypeSystemSPWrapper &other) const;
78+
bool operator!=(const TypeSystemSPWrapper &other) const {
79+
return !(*this == other);
80+
}
81+
82+
/// Only to be used in a one-off situations like
83+
/// if (typesystem && typesystem->method())
84+
/// Do not store this pointer!
85+
TypeSystem *operator->() const;
86+
87+
lldb::TypeSystemSP GetSharedPointer() const { return m_typesystem_sp; }
88+
};
89+
90+
CompilerType(TypeSystemSPWrapper type_system, lldb::opaque_compiler_type_t type)
91+
: m_type_system(type_system.GetSharedPointer()), m_type(type) {
4392
assert(Verify() && "verification failed");
4493
}
4594

4695
CompilerType(const CompilerType &rhs)
47-
: m_type(rhs.m_type), m_type_system(rhs.m_type_system) {}
96+
: m_type_system(rhs.m_type_system), m_type(rhs.m_type) {}
4897

4998
CompilerType() = default;
5099

51100
/// Operators.
52101
/// \{
53102
const CompilerType &operator=(const CompilerType &rhs) {
54-
m_type = rhs.m_type;
55103
m_type_system = rhs.m_type_system;
104+
m_type = rhs.m_type;
56105
return *this;
57106
}
58107

59108
bool operator<(const CompilerType &rhs) const {
60-
if (m_type_system == rhs.m_type_system)
109+
auto lts = m_type_system.lock();
110+
auto rts = rhs.m_type_system.lock();
111+
if (lts.get() == rts.get())
61112
return m_type < rhs.m_type;
62-
return m_type_system < rhs.m_type_system;
113+
return lts.get() < rts.get();
63114
}
64115
/// \}
65116

66117
/// Tests.
67118
/// \{
68119
explicit operator bool() const {
69-
return m_type != nullptr && m_type_system != nullptr;
120+
return m_type_system.lock() && m_type;
70121
}
71122

72-
bool IsValid() const { return m_type != nullptr && m_type_system != nullptr; }
123+
bool IsValid() const { return (bool)*this; }
73124

74125
bool IsArrayType(CompilerType *element_type = nullptr,
75126
uint64_t *size = nullptr,
@@ -159,7 +210,10 @@ class CompilerType {
159210

160211
/// Accessors.
161212
/// \{
162-
TypeSystem *GetTypeSystem() const { return m_type_system; }
213+
214+
/// Returns a shared pointer to the type system. The
215+
/// TypeSystem::TypeSystemSPWrapper can be compared for equality.
216+
TypeSystemSPWrapper GetTypeSystem() const;
163217

164218
ConstString GetTypeName(bool BaseOnly = false) const;
165219

@@ -174,7 +228,9 @@ class CompilerType {
174228

175229
lldb::TypeClass GetTypeClass() const;
176230

177-
void SetCompilerType(TypeSystem *type_system,
231+
void SetCompilerType(lldb::TypeSystemWP type_system,
232+
lldb::opaque_compiler_type_t type);
233+
void SetCompilerType(TypeSystemSPWrapper type_system,
178234
lldb::opaque_compiler_type_t type);
179235

180236
unsigned GetTypeQualifiers() const;
@@ -407,8 +463,8 @@ class CompilerType {
407463
size_t data_byte_size, Scalar &value,
408464
ExecutionContextScope *exe_scope) const;
409465
void Clear() {
466+
m_type_system = {};
410467
m_type = nullptr;
411-
m_type_system = nullptr;
412468
}
413469

414470
private:
@@ -419,8 +475,8 @@ class CompilerType {
419475
bool Verify() const;
420476
#endif
421477

478+
lldb::TypeSystemWP m_type_system;
422479
lldb::opaque_compiler_type_t m_type = nullptr;
423-
TypeSystem *m_type_system = nullptr;
424480
};
425481

426482
bool operator==(const CompilerType &lhs, const CompilerType &rhs);

lldb/include/lldb/Symbol/SymbolFile.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,7 @@ class SymbolFile : public PluginInterface {
310310

311311
virtual void PreloadSymbols();
312312

313-
virtual llvm::Expected<lldb_private::TypeSystem &>
313+
virtual llvm::Expected<lldb::TypeSystemSP>
314314
GetTypeSystemForLanguage(lldb::LanguageType language) = 0;
315315

316316
virtual CompilerDeclContext
@@ -465,7 +465,7 @@ class SymbolFileCommon : public SymbolFile {
465465
uint32_t GetNumCompileUnits() override;
466466
lldb::CompUnitSP GetCompileUnitAtIndex(uint32_t idx) override;
467467

468-
llvm::Expected<lldb_private::TypeSystem &>
468+
llvm::Expected<lldb::TypeSystemSP>
469469
GetTypeSystemForLanguage(lldb::LanguageType language) override;
470470

471471
void Dump(Stream &s) override;

lldb/include/lldb/Symbol/SymbolFileOnDemand.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ class SymbolFileOnDemand : public lldb_private::SymbolFile {
167167
lldb::TypeClass type_mask,
168168
lldb_private::TypeList &type_list) override;
169169

170-
llvm::Expected<lldb_private::TypeSystem &>
170+
llvm::Expected<lldb::TypeSystemSP>
171171
GetTypeSystemForLanguage(lldb::LanguageType language) override;
172172

173173
lldb_private::CompilerDeclContext FindNamespace(

lldb/include/lldb/Symbol/TaggedASTType.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ template <unsigned int C> class TaggedASTType : public CompilerType {
2020
TaggedASTType(const CompilerType &compiler_type)
2121
: CompilerType(compiler_type) {}
2222

23-
TaggedASTType(lldb::opaque_compiler_type_t type, TypeSystem *type_system)
23+
TaggedASTType(lldb::opaque_compiler_type_t type,
24+
lldb::TypeSystemWP type_system)
2425
: CompilerType(type_system, type) {}
2526

2627
TaggedASTType(const TaggedASTType<C> &tw) : CompilerType(tw) {}

lldb/include/lldb/Symbol/Type.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -297,7 +297,7 @@ class TypeImpl {
297297

298298
CompilerType GetCompilerType(bool prefer_dynamic);
299299

300-
TypeSystem *GetTypeSystem(bool prefer_dynamic);
300+
CompilerType::TypeSystemSPWrapper GetTypeSystem(bool prefer_dynamic);
301301

302302
bool GetDescription(lldb_private::Stream &strm,
303303
lldb::DescriptionLevel description_level);

lldb/include/lldb/Symbol/TypeSystem.h

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,12 @@
1010
#define LLDB_SYMBOL_TYPESYSTEM_H
1111

1212
#include <functional>
13-
#include <map>
1413
#include <mutex>
1514
#include <string>
1615

1716
#include "llvm/ADT/APFloat.h"
1817
#include "llvm/ADT/APSInt.h"
18+
#include "llvm/ADT/DenseMap.h"
1919
#include "llvm/ADT/SmallBitVector.h"
2020
#include "llvm/Support/Casting.h"
2121
#include "llvm/Support/Error.h"
@@ -72,7 +72,8 @@ struct LanguageSet {
7272
/// \see lldb_private::CompilerType
7373
/// \see lldb_private::CompilerDecl
7474
/// \see lldb_private::CompilerDeclContext
75-
class TypeSystem : public PluginInterface {
75+
class TypeSystem : public PluginInterface,
76+
public std::enable_shared_from_this<TypeSystem> {
7677
public:
7778
// Constructors and Destructors
7879
~TypeSystem() override;
@@ -86,10 +87,10 @@ class TypeSystem : public PluginInterface {
8687
static lldb::TypeSystemSP CreateInstance(lldb::LanguageType language,
8788
Target *target);
8889

89-
// Free up any resources associated with this TypeSystem. Done before
90-
// removing all the TypeSystems from the TypeSystemMap.
90+
/// Free up any resources associated with this TypeSystem. Done before
91+
/// removing all the TypeSystems from the TypeSystemMap.
9192
virtual void Finalize() {}
92-
93+
9394
virtual DWARFASTParser *GetDWARFParser() { return nullptr; }
9495
virtual PDBASTParser *GetPDBParser() { return nullptr; }
9596
virtual npdb::PdbAstBuilder *GetNativePDBParser() { return nullptr; }
@@ -526,39 +527,41 @@ class TypeSystemMap {
526527

527528
// Iterate through all of the type systems that are created. Return true from
528529
// callback to keep iterating, false to stop iterating.
529-
void ForEach(std::function<bool(TypeSystem *)> const &callback);
530+
void ForEach(std::function<bool(lldb::TypeSystemSP)> const &callback);
530531

531-
llvm::Expected<TypeSystem &>
532+
llvm::Expected<lldb::TypeSystemSP>
532533
GetTypeSystemForLanguage(lldb::LanguageType language, Module *module,
533534
bool can_create);
534535

535-
llvm::Expected<TypeSystem &>
536+
llvm::Expected<lldb::TypeSystemSP>
536537
GetTypeSystemForLanguage(lldb::LanguageType language, Target *target,
537538
bool can_create);
538539

539540
protected:
540-
typedef std::map<lldb::LanguageType, lldb::TypeSystemSP> collection;
541+
typedef llvm::DenseMap<uint16_t, lldb::TypeSystemSP> collection;
541542
mutable std::mutex m_mutex; ///< A mutex to keep this object happy in
542-
///multi-threaded environments.
543+
/// multi-threaded environments.
543544
collection m_map;
544545
bool m_clear_in_progress = false;
545546

546547
private:
547548
typedef llvm::function_ref<lldb::TypeSystemSP()> CreateCallback;
548549
/// Finds the type system for the given language. If no type system could be
549-
/// found for a language and a CreateCallback was provided, the value returned
550-
/// by the callback will be treated as the TypeSystem for the language.
550+
/// found for a language and a CreateCallback was provided, the value
551+
/// returned by the callback will be treated as the TypeSystem for the
552+
/// language.
551553
///
552554
/// \param language The language for which the type system should be found.
553555
/// \param create_callback A callback that will be called if no previously
554556
/// created TypeSystem that fits the given language
555557
/// could found. Can be omitted if a non-existent
556-
/// type system should be treated as an error instead.
558+
/// type system should be treated as an error
559+
/// instead.
557560
/// \return The found type system or an error.
558-
llvm::Expected<TypeSystem &> GetTypeSystemForLanguage(
561+
llvm::Expected<lldb::TypeSystemSP> GetTypeSystemForLanguage(
559562
lldb::LanguageType language,
560563
llvm::Optional<CreateCallback> create_callback = llvm::None);
561-
};
564+
};
562565

563566
} // namespace lldb_private
564567

lldb/include/lldb/Target/Target.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1119,11 +1119,12 @@ class Target : public std::enable_shared_from_this<Target>,
11191119

11201120
PathMappingList &GetImageSearchPathList();
11211121

1122-
llvm::Expected<TypeSystem &>
1122+
llvm::Expected<lldb::TypeSystemSP>
11231123
GetScratchTypeSystemForLanguage(lldb::LanguageType language,
11241124
bool create_on_demand = true);
11251125

1126-
std::vector<TypeSystem *> GetScratchTypeSystems(bool create_on_demand = true);
1126+
std::vector<lldb::TypeSystemSP>
1127+
GetScratchTypeSystems(bool create_on_demand = true);
11271128

11281129
PersistentExpressionState *
11291130
GetPersistentExpressionStateForLanguage(lldb::LanguageType language);

lldb/include/lldb/lldb-enumerations.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#ifndef LLDB_LLDB_ENUMERATIONS_H
1010
#define LLDB_LLDB_ENUMERATIONS_H
1111

12+
#include <cstdint>
1213
#include <type_traits>
1314

1415
#ifndef SWIG
@@ -433,7 +434,7 @@ FLAGS_ENUM(WatchpointEventType){
433434
/// specification for ease of use and consistency.
434435
/// The enum -> string code is in Language.cpp, don't change this
435436
/// table without updating that code as well.
436-
enum LanguageType {
437+
enum LanguageType : uint16_t {
437438
eLanguageTypeUnknown = 0x0000, ///< Unknown or invalid language value.
438439
eLanguageTypeC89 = 0x0001, ///< ISO C:1989.
439440
eLanguageTypeC = 0x0002, ///< Non-standardized C, such as K&R.

lldb/include/lldb/lldb-forward.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -432,6 +432,7 @@ typedef std::shared_ptr<lldb_private::TypeMemberFunctionImpl>
432432
typedef std::shared_ptr<lldb_private::TypeEnumMemberImpl> TypeEnumMemberImplSP;
433433
typedef std::shared_ptr<lldb_private::TypeFilterImpl> TypeFilterImplSP;
434434
typedef std::shared_ptr<lldb_private::TypeSystem> TypeSystemSP;
435+
typedef std::weak_ptr<lldb_private::TypeSystem> TypeSystemWP;
435436
typedef std::shared_ptr<lldb_private::TypeFormatImpl> TypeFormatImplSP;
436437
typedef std::shared_ptr<lldb_private::TypeNameSpecifierImpl>
437438
TypeNameSpecifierImplSP;

0 commit comments

Comments
 (0)