aboutsummaryrefslogtreecommitdiff
path: root/lldb
diff options
context:
space:
mode:
Diffstat (limited to 'lldb')
-rw-r--r--lldb/include/lldb/API/SBDebugger.h3
-rw-r--r--lldb/include/lldb/API/SBTarget.h8
-rw-r--r--lldb/include/lldb/Target/Target.h14
-rw-r--r--lldb/include/lldb/Target/TargetList.h11
-rw-r--r--lldb/include/lldb/lldb-defines.h1
-rw-r--r--lldb/source/API/SBDebugger.cpp11
-rw-r--r--lldb/source/API/SBTarget.cpp8
-rw-r--r--lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp6
-rw-r--r--lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp19
-rw-r--r--lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp83
-rw-r--r--lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h20
-rw-r--r--lldb/source/Target/Target.cpp3
-rw-r--r--lldb/source/Target/TargetList.cpp12
-rw-r--r--lldb/test/API/python_api/debugger/TestDebuggerAPI.py147
-rw-r--r--lldb/test/Shell/SymbolFile/NativePDB/break-by-function.cpp6
-rw-r--r--lldb/test/Shell/SymbolFile/NativePDB/break-by-line.cpp2
-rw-r--r--lldb/test/Shell/SymbolFile/NativePDB/c-calling-conventions.cpp51
-rw-r--r--lldb/test/Shell/SymbolFile/NativePDB/disassembly.cpp2
-rw-r--r--lldb/test/Shell/SymbolFile/NativePDB/find-functions.cpp7
-rw-r--r--lldb/test/Shell/SymbolFile/NativePDB/local-variables.cpp10
-rw-r--r--lldb/test/Shell/SymbolFile/NativePDB/stack_unwinding01.cpp12
-rw-r--r--lldb/test/Shell/SymbolFile/PDB/function-nested-block.test2
-rw-r--r--lldb/test/Shell/SymbolFile/PDB/variables.test6
-rw-r--r--lldb/tools/debugserver/source/RNBRemote.cpp177
-rw-r--r--lldb/unittests/Host/MainLoopTest.cpp2
25 files changed, 480 insertions, 143 deletions
diff --git a/lldb/include/lldb/API/SBDebugger.h b/lldb/include/lldb/API/SBDebugger.h
index f77b0c1..7a08a08 100644
--- a/lldb/include/lldb/API/SBDebugger.h
+++ b/lldb/include/lldb/API/SBDebugger.h
@@ -359,6 +359,9 @@ public:
lldb::SBTarget FindTargetWithFileAndArch(const char *filename,
const char *arch);
+ /// Find a target with the specified unique ID.
+ lldb::SBTarget FindTargetByGloballyUniqueID(lldb::user_id_t id);
+
/// Get the number of targets in the debugger.
uint32_t GetNumTargets();
diff --git a/lldb/include/lldb/API/SBTarget.h b/lldb/include/lldb/API/SBTarget.h
index 62cdd34..173fd05 100644
--- a/lldb/include/lldb/API/SBTarget.h
+++ b/lldb/include/lldb/API/SBTarget.h
@@ -357,6 +357,14 @@ public:
const char *GetLabel() const;
+ /// Get the globally unique ID for this target. This ID is unique
+ /// across all debugger instances within the same lldb process.
+ ///
+ /// \return
+ /// The globally unique ID for this target, or
+ /// LLDB_INVALID_GLOBALLY_UNIQUE_TARGET_ID if the target is invalid.
+ lldb::user_id_t GetGloballyUniqueID() const;
+
SBError SetLabel(const char *label);
/// Architecture opcode byte size width accessor
diff --git a/lldb/include/lldb/Target/Target.h b/lldb/include/lldb/Target/Target.h
index 14a09f2..f4a0923 100644
--- a/lldb/include/lldb/Target/Target.h
+++ b/lldb/include/lldb/Target/Target.h
@@ -600,6 +600,17 @@ public:
bool IsDummyTarget() const { return m_is_dummy_target; }
+ /// Get the globally unique ID for this target.
+ ///
+ /// This ID is unique across all debugger instances and all targets,
+ /// within the same lldb process. The ID is assigned
+ /// during target construction and remains constant for the target's lifetime.
+ /// The first target created (typically the dummy target) gets ID 1.
+ ///
+ /// \return
+ /// The globally unique ID for this target.
+ lldb::user_id_t GetGloballyUniqueID() const { return m_target_unique_id; }
+
const std::string &GetLabel() const { return m_label; }
/// Set a label for a target.
@@ -1651,6 +1662,9 @@ protected:
bool m_suppress_stop_hooks; /// Used to not run stop hooks for expressions
bool m_is_dummy_target;
unsigned m_next_persistent_variable_index = 0;
+ lldb::user_id_t m_target_unique_id =
+ LLDB_INVALID_GLOBALLY_UNIQUE_TARGET_ID; /// The globally unique ID
+ /// assigned to this target
/// An optional \a lldb_private::Trace object containing processor trace
/// information of this target.
lldb::TraceSP m_trace_sp;
diff --git a/lldb/include/lldb/Target/TargetList.h b/lldb/include/lldb/Target/TargetList.h
index 080a603..8827251 100644
--- a/lldb/include/lldb/Target/TargetList.h
+++ b/lldb/include/lldb/Target/TargetList.h
@@ -159,6 +159,17 @@ public:
lldb::TargetSP FindTargetWithProcess(lldb_private::Process *process) const;
+ /// Find the target that has a globally unique ID that matches ID \a id.
+ ///
+ /// \param[in] id
+ /// The globally unique target ID to search our target list for.
+ ///
+ /// \return
+ /// A shared pointer to a target object. The returned shared
+ /// pointer will contain nullptr if no target objects has a
+ /// matching target ID.
+ lldb::TargetSP FindTargetByGloballyUniqueID(lldb::user_id_t id) const;
+
lldb::TargetSP GetTargetSP(Target *target) const;
/// Send an async interrupt to one or all processes.
diff --git a/lldb/include/lldb/lldb-defines.h b/lldb/include/lldb/lldb-defines.h
index c7bd019..c54ef88 100644
--- a/lldb/include/lldb/lldb-defines.h
+++ b/lldb/include/lldb/lldb-defines.h
@@ -96,6 +96,7 @@
#define LLDB_INVALID_QUEUE_ID 0
#define LLDB_INVALID_CPU_ID UINT32_MAX
#define LLDB_INVALID_WATCHPOINT_RESOURCE_ID UINT32_MAX
+#define LLDB_INVALID_GLOBALLY_UNIQUE_TARGET_ID 0
/// CPU Type definitions
#define LLDB_ARCH_DEFAULT "systemArch"
diff --git a/lldb/source/API/SBDebugger.cpp b/lldb/source/API/SBDebugger.cpp
index 603e306..5c4c653 100644
--- a/lldb/source/API/SBDebugger.cpp
+++ b/lldb/source/API/SBDebugger.cpp
@@ -983,6 +983,17 @@ uint32_t SBDebugger::GetIndexOfTarget(lldb::SBTarget target) {
return m_opaque_sp->GetTargetList().GetIndexOfTarget(target.GetSP());
}
+SBTarget SBDebugger::FindTargetByGloballyUniqueID(lldb::user_id_t id) {
+ LLDB_INSTRUMENT_VA(this, id);
+ SBTarget sb_target;
+ if (m_opaque_sp) {
+ // No need to lock, the target list is thread safe
+ sb_target.SetSP(
+ m_opaque_sp->GetTargetList().FindTargetByGloballyUniqueID(id));
+ }
+ return sb_target;
+}
+
SBTarget SBDebugger::FindTargetWithProcessID(lldb::pid_t pid) {
LLDB_INSTRUMENT_VA(this, pid);
diff --git a/lldb/source/API/SBTarget.cpp b/lldb/source/API/SBTarget.cpp
index 0d03250..98d10aa 100644
--- a/lldb/source/API/SBTarget.cpp
+++ b/lldb/source/API/SBTarget.cpp
@@ -1633,6 +1633,14 @@ const char *SBTarget::GetLabel() const {
return nullptr;
}
+lldb::user_id_t SBTarget::GetGloballyUniqueID() const {
+ LLDB_INSTRUMENT_VA(this);
+
+ if (TargetSP target_sp = GetSP())
+ return target_sp->GetGloballyUniqueID();
+ return LLDB_INVALID_GLOBALLY_UNIQUE_TARGET_ID;
+}
+
SBError SBTarget::SetLabel(const char *label) {
LLDB_INSTRUMENT_VA(this, label);
diff --git a/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp b/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp
index 9c798cb..7ef50da 100644
--- a/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp
+++ b/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp
@@ -218,8 +218,8 @@ static Status EnsureFDFlags(int fd, int flags) {
static llvm::Error AddPtraceScopeNote(llvm::Error original_error) {
Expected<int> ptrace_scope = GetPtraceScope();
if (auto E = ptrace_scope.takeError()) {
- Log *log = GetLog(POSIXLog::Process);
- LLDB_LOG(log, "error reading value of ptrace_scope: {0}", E);
+ LLDB_LOG_ERROR(GetLog(POSIXLog::Process), std::move(E),
+ "error reading value of ptrace_scope: {0}");
// The original error is probably more interesting than not being able to
// read or interpret ptrace_scope.
@@ -230,6 +230,7 @@ static llvm::Error AddPtraceScopeNote(llvm::Error original_error) {
switch (*ptrace_scope) {
case 1:
case 2:
+ llvm::consumeError(std::move(original_error));
return llvm::createStringError(
std::error_code(errno, std::generic_category()),
"The current value of ptrace_scope is %d, which can cause ptrace to "
@@ -239,6 +240,7 @@ static llvm::Error AddPtraceScopeNote(llvm::Error original_error) {
"https://www.kernel.org/doc/Documentation/security/Yama.txt.",
*ptrace_scope);
case 3:
+ llvm::consumeError(std::move(original_error));
return llvm::createStringError(
std::error_code(errno, std::generic_category()),
"The current value of ptrace_scope is 3, which will cause ptrace to "
diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp
index 51bdcc9..e7fddf0 100644
--- a/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp
+++ b/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp
@@ -38,16 +38,18 @@ struct CreateMethodDecl : public TypeVisitorCallbacks {
TypeIndex func_type_index,
clang::FunctionDecl *&function_decl,
lldb::opaque_compiler_type_t parent_ty,
- llvm::StringRef proc_name, CompilerType func_ct)
+ llvm::StringRef proc_name, ConstString mangled_name,
+ CompilerType func_ct)
: m_index(m_index), m_clang(m_clang), func_type_index(func_type_index),
function_decl(function_decl), parent_ty(parent_ty),
- proc_name(proc_name), func_ct(func_ct) {}
+ proc_name(proc_name), mangled_name(mangled_name), func_ct(func_ct) {}
PdbIndex &m_index;
TypeSystemClang &m_clang;
TypeIndex func_type_index;
clang::FunctionDecl *&function_decl;
lldb::opaque_compiler_type_t parent_ty;
llvm::StringRef proc_name;
+ ConstString mangled_name;
CompilerType func_ct;
llvm::Error visitKnownMember(CVMemberRecord &cvr,
@@ -87,8 +89,7 @@ struct CreateMethodDecl : public TypeVisitorCallbacks {
bool is_artificial = (options & MethodOptions::CompilerGenerated) ==
MethodOptions::CompilerGenerated;
function_decl = m_clang.AddMethodToCXXRecordType(
- parent_ty, proc_name,
- /*asm_label=*/{}, func_ct, /*access=*/access_type,
+ parent_ty, proc_name, mangled_name, func_ct, /*access=*/access_type,
/*is_virtual=*/is_virtual, /*is_static=*/is_static,
/*is_inline=*/false, /*is_explicit=*/false,
/*is_attr_used=*/false, /*is_artificial=*/is_artificial);
@@ -892,6 +893,10 @@ PdbAstBuilder::CreateFunctionDecl(PdbCompilandSymId func_id,
tag_record = CVTagRecord::create(index.tpi().getType(*eti)).asTag();
}
}
+
+ ConstString mangled_name(
+ pdb->FindMangledFunctionName(func_id).value_or(llvm::StringRef()));
+
if (!tag_record.FieldList.isSimple()) {
CVType field_list_cvt = index.tpi().getType(tag_record.FieldList);
FieldListRecord field_list;
@@ -899,15 +904,15 @@ PdbAstBuilder::CreateFunctionDecl(PdbCompilandSymId func_id,
field_list_cvt, field_list))
llvm::consumeError(std::move(error));
CreateMethodDecl process(index, m_clang, func_ti, function_decl,
- parent_opaque_ty, func_name, func_ct);
+ parent_opaque_ty, func_name, mangled_name,
+ func_ct);
if (llvm::Error err = visitMemberRecordStream(field_list.Data, process))
llvm::consumeError(std::move(err));
}
if (!function_decl) {
function_decl = m_clang.AddMethodToCXXRecordType(
- parent_opaque_ty, func_name,
- /*asm_label=*/{}, func_ct,
+ parent_opaque_ty, func_name, mangled_name, func_ct,
/*access=*/lldb::AccessType::eAccessPublic,
/*is_virtual=*/false, /*is_static=*/false,
/*is_inline=*/false, /*is_explicit=*/false,
diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
index 8b3d775..75a8189 100644
--- a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
+++ b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
@@ -501,7 +501,11 @@ lldb::FunctionSP SymbolFileNativePDB::CreateFunction(PdbCompilandSymId func_id,
return nullptr;
PdbTypeSymId sig_id(proc.FunctionType, false);
- Mangled mangled(proc.Name);
+
+ std::optional<llvm::StringRef> mangled_opt = FindMangledSymbol(
+ SegmentOffset(proc.Segment, proc.CodeOffset), proc.FunctionType);
+ Mangled mangled(mangled_opt.value_or(proc.Name));
+
FunctionSP func_sp = std::make_shared<Function>(
&comp_unit, toOpaqueUid(func_id), toOpaqueUid(sig_id), mangled,
func_type.get(), func_addr,
@@ -2662,6 +2666,83 @@ SymbolFileNativePDB::GetContextForType(TypeIndex ti) {
return ctx;
}
+std::optional<llvm::StringRef>
+SymbolFileNativePDB::FindMangledFunctionName(PdbCompilandSymId func_id) {
+ const CompilandIndexItem *cci =
+ m_index->compilands().GetCompiland(func_id.modi);
+ if (!cci)
+ return std::nullopt;
+
+ CVSymbol sym_record = cci->m_debug_stream.readSymbolAtOffset(func_id.offset);
+ if (sym_record.kind() != S_LPROC32 && sym_record.kind() != S_GPROC32)
+ return std::nullopt;
+
+ ProcSym proc(static_cast<SymbolRecordKind>(sym_record.kind()));
+ cantFail(SymbolDeserializer::deserializeAs<ProcSym>(sym_record, proc));
+
+ return FindMangledSymbol(SegmentOffset(proc.Segment, proc.CodeOffset),
+ proc.FunctionType);
+}
+
+std::optional<llvm::StringRef>
+SymbolFileNativePDB::FindMangledSymbol(SegmentOffset so,
+ TypeIndex function_type) {
+ auto symbol = m_index->publics().findByAddress(m_index->symrecords(),
+ so.segment, so.offset);
+ if (!symbol)
+ return std::nullopt;
+
+ llvm::StringRef name = symbol->first.Name;
+ // For functions, we might need to strip the mangled name. See
+ // StripMangledFunctionName for more info.
+ if (!function_type.isNoneType() &&
+ (symbol->first.Flags & PublicSymFlags::Function) != PublicSymFlags::None)
+ name = StripMangledFunctionName(name, function_type);
+
+ return name;
+}
+
+llvm::StringRef
+SymbolFileNativePDB::StripMangledFunctionName(const llvm::StringRef mangled,
+ PdbTypeSymId func_ty) {
+ // "In non-64 bit environments" (on x86 in pactice), __cdecl functions get
+ // prefixed with an underscore. For compilers using LLVM, this happens in LLVM
+ // (as opposed to the compiler frontend). Because of this, DWARF doesn't
+ // contain the "full" mangled name in DW_AT_linkage_name for these functions.
+ // We strip the mangling here for compatibility with DWARF. See
+ // llvm.org/pr161676 and
+ // https://learn.microsoft.com/en-us/cpp/build/reference/decorated-names#FormatC
+
+ if (!mangled.starts_with('_') ||
+ m_index->dbi().getMachineType() != PDB_Machine::x86)
+ return mangled;
+
+ CVType cvt = m_index->tpi().getType(func_ty.index);
+ PDB_CallingConv cc = PDB_CallingConv::NearC;
+ if (cvt.kind() == LF_PROCEDURE) {
+ ProcedureRecord proc;
+ if (llvm::Error error =
+ TypeDeserializer::deserializeAs<ProcedureRecord>(cvt, proc))
+ llvm::consumeError(std::move(error));
+ cc = proc.CallConv;
+ } else if (cvt.kind() == LF_MFUNCTION) {
+ MemberFunctionRecord mfunc;
+ if (llvm::Error error =
+ TypeDeserializer::deserializeAs<MemberFunctionRecord>(cvt, mfunc))
+ llvm::consumeError(std::move(error));
+ cc = mfunc.CallConv;
+ } else {
+ LLDB_LOG(GetLog(LLDBLog::Symbols), "Unexpected function type, got {0}",
+ cvt.kind());
+ return mangled;
+ }
+
+ if (cc == PDB_CallingConv::NearC || cc == PDB_CallingConv::FarC)
+ return mangled.drop_front();
+
+ return mangled;
+}
+
void SymbolFileNativePDB::CacheUdtDeclarations() {
for (CVType cvt : m_index->ipi().typeArray()) {
switch (cvt.kind()) {
diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h
index 2405f8b..a5fef35 100644
--- a/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h
+++ b/lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.h
@@ -140,6 +140,12 @@ public:
std::optional<PdbCompilandSymId> FindSymbolScope(PdbCompilandSymId id);
+ /// Find the mangled name for a function
+ ///
+ /// \param id A symbol ID of a S_LPROC32/S_GPROC32 record
+ /// \returns The mangled name of the function (if available)
+ std::optional<llvm::StringRef> FindMangledFunctionName(PdbCompilandSymId id);
+
void FindTypes(const lldb_private::TypeQuery &match,
lldb_private::TypeResults &results) override;
@@ -269,6 +275,20 @@ private:
void CacheUdtDeclarations();
llvm::Expected<Declaration> ResolveUdtDeclaration(PdbTypeSymId type_id);
+ /// Find a symbol name at a specific address (`so`).
+ ///
+ /// \param[in] so The segment and offset where the symbol is located.
+ /// \param[in] function_type If the symbol is expected to be a function, this
+ /// has to be the type of the function. It's used to strip the name of
+ /// __cdecl functions on x86.
+ /// \returns The mangled symbol name if found, otherwise `std::nullopt`.
+ std::optional<llvm::StringRef> FindMangledSymbol(
+ SegmentOffset so,
+ llvm::codeview::TypeIndex function_type = llvm::codeview::TypeIndex());
+
+ llvm::StringRef StripMangledFunctionName(llvm::StringRef mangled,
+ PdbTypeSymId func_ty);
+
llvm::BumpPtrAllocator m_allocator;
lldb::addr_t m_obj_load_address = 0;
diff --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp
index fa98c24..e0286c4 100644
--- a/lldb/source/Target/Target.cpp
+++ b/lldb/source/Target/Target.cpp
@@ -139,6 +139,8 @@ private:
};
} // namespace
+static std::atomic<lldb::user_id_t> g_target_unique_id{1};
+
template <typename Installer>
static Status installExecutable(const Installer &installer) {
if (!installer.m_local_file || !installer.m_remote_file)
@@ -183,6 +185,7 @@ Target::Target(Debugger &debugger, const ArchSpec &target_arch,
m_source_manager_up(), m_stop_hooks(), m_stop_hook_next_id(0),
m_latest_stop_hook_id(0), m_valid(true), m_suppress_stop_hooks(false),
m_is_dummy_target(is_dummy_target),
+ m_target_unique_id(g_target_unique_id++),
m_frame_recognizer_manager_up(
std::make_unique<StackFrameRecognizerManager>()) {
SetEventName(eBroadcastBitBreakpointChanged, "breakpoint-changed");
diff --git a/lldb/source/Target/TargetList.cpp b/lldb/source/Target/TargetList.cpp
index 7037dc2..188c250 100644
--- a/lldb/source/Target/TargetList.cpp
+++ b/lldb/source/Target/TargetList.cpp
@@ -428,6 +428,18 @@ TargetSP TargetList::FindTargetWithProcess(Process *process) const {
return target_sp;
}
+TargetSP TargetList::FindTargetByGloballyUniqueID(lldb::user_id_t id) const {
+ std::lock_guard<std::recursive_mutex> guard(m_target_list_mutex);
+ auto it = llvm::find_if(m_target_list, [id](const TargetSP &item) {
+ return item->GetGloballyUniqueID() == id;
+ });
+
+ if (it != m_target_list.end())
+ return *it;
+
+ return TargetSP();
+}
+
TargetSP TargetList::GetTargetSP(Target *target) const {
TargetSP target_sp;
if (!target)
diff --git a/lldb/test/API/python_api/debugger/TestDebuggerAPI.py b/lldb/test/API/python_api/debugger/TestDebuggerAPI.py
index 43f45f3..44b1183 100644
--- a/lldb/test/API/python_api/debugger/TestDebuggerAPI.py
+++ b/lldb/test/API/python_api/debugger/TestDebuggerAPI.py
@@ -294,3 +294,150 @@ class DebuggerAPITestCase(TestBase):
self.assertEqual(instance_str, class_str)
self.assertEqual(class_str, property_str)
+
+ def test_find_target_with_unique_id(self):
+ """Test SBDebugger.FindTargetByGloballyUniqueID() functionality."""
+
+ # Test with invalid ID - should return invalid target
+ invalid_target = self.dbg.FindTargetByGloballyUniqueID(999999)
+ self.assertFalse(invalid_target.IsValid())
+
+ # Test with ID 0 - should return invalid target
+ zero_target = self.dbg.FindTargetByGloballyUniqueID(0)
+ self.assertFalse(zero_target.IsValid())
+
+ # Build a real executable and create target with it
+ self.build()
+ exe = self.getBuildArtifact("a.out")
+ target = self.dbg.CreateTarget(exe)
+ self.assertTrue(target.IsValid())
+
+ # Find the target using its unique ID
+ unique_id = target.GetGloballyUniqueID()
+ self.assertNotEqual(unique_id, lldb.LLDB_INVALID_GLOBALLY_UNIQUE_TARGET_ID)
+ found_target = self.dbg.FindTargetByGloballyUniqueID(unique_id)
+ self.assertTrue(found_target.IsValid())
+ self.assertEqual(
+ self.dbg.GetIndexOfTarget(target), self.dbg.GetIndexOfTarget(found_target)
+ )
+ self.assertEqual(found_target.GetGloballyUniqueID(), unique_id)
+
+ def test_target_unique_id_uniqueness(self):
+ """Test that Target.GetGloballyUniqueID() returns unique values across multiple targets."""
+
+ # Create multiple targets and verify they all have unique IDs
+ self.build()
+ exe = self.getBuildArtifact("a.out")
+ targets = []
+ unique_ids = set()
+
+ for i in range(10):
+ target = self.dbg.CreateTarget(exe)
+ self.assertTrue(target.IsValid())
+
+ unique_id = target.GetGloballyUniqueID()
+ self.assertNotEqual(unique_id, 0)
+
+ # Verify this ID hasn't been used before
+ self.assertNotIn(
+ unique_id, unique_ids, f"Duplicate unique ID found: {unique_id}"
+ )
+
+ unique_ids.add(unique_id)
+ targets.append(target)
+
+ # Verify all targets can still be found by their IDs
+ for target in targets:
+ unique_id = target.GetGloballyUniqueID()
+ found = self.dbg.FindTargetByGloballyUniqueID(unique_id)
+ self.assertTrue(found.IsValid())
+ self.assertEqual(found.GetGloballyUniqueID(), unique_id)
+
+ def test_target_unique_id_uniqueness_after_deletion(self):
+ """Test finding targets have unique ID after target deletion."""
+ # Create two targets
+ self.build()
+ exe = self.getBuildArtifact("a.out")
+ target1 = self.dbg.CreateTarget(exe)
+ target2 = self.dbg.CreateTarget(exe)
+ self.assertTrue(target1.IsValid())
+ self.assertTrue(target2.IsValid())
+
+ unique_id1 = target1.GetGloballyUniqueID()
+ unique_id2 = target2.GetGloballyUniqueID()
+ self.assertNotEqual(unique_id1, 0)
+ self.assertNotEqual(unique_id2, 0)
+ self.assertNotEqual(unique_id1, unique_id2)
+
+ # Verify we can find them initially
+ found_target1 = self.dbg.FindTargetByGloballyUniqueID(unique_id1)
+ found_target2 = self.dbg.FindTargetByGloballyUniqueID(unique_id2)
+ self.assertTrue(found_target1.IsValid())
+ self.assertTrue(found_target2.IsValid())
+ target2_index = self.dbg.GetIndexOfTarget(target2)
+
+ # Delete target 2
+ deleted = self.dbg.DeleteTarget(target2)
+ self.assertTrue(deleted)
+
+ # Try to find the deleted target - should not be found
+ not_found_target = self.dbg.FindTargetByGloballyUniqueID(unique_id2)
+ self.assertFalse(not_found_target.IsValid())
+
+ # Create a new target
+ target3 = self.dbg.CreateTarget(exe)
+ self.assertTrue(target3.IsValid())
+ # Target list index of target3 should be the same as target2's
+ # since it was deleted, but it should have a distinct unique ID
+ target3_index = self.dbg.GetIndexOfTarget(target3)
+ unique_id3 = target3.GetGloballyUniqueID()
+ self.assertEqual(target3_index, target2_index)
+ self.assertNotEqual(unique_id3, unique_id2)
+ self.assertNotEqual(unique_id3, unique_id1)
+ # Make sure we can find the new target
+ found_target3 = self.dbg.FindTargetByGloballyUniqueID(
+ target3.GetGloballyUniqueID()
+ )
+ self.assertTrue(found_target3.IsValid())
+
+ def test_target_globally_unique_id_across_debuggers(self):
+ """Test that target IDs are globally unique across multiple debuggers."""
+ self.build()
+ exe = self.getBuildArtifact("a.out")
+
+ # Create two debuggers with targets each
+ debugger1 = lldb.SBDebugger.Create()
+ debugger2 = lldb.SBDebugger.Create()
+ self.addTearDownHook(lambda: lldb.SBDebugger.Destroy(debugger1))
+ self.addTearDownHook(lambda: lldb.SBDebugger.Destroy(debugger2))
+
+ # Create 2 targets per debugger
+ targets_d1 = [debugger1.CreateTarget(exe), debugger1.CreateTarget(exe)]
+ targets_d2 = [debugger2.CreateTarget(exe), debugger2.CreateTarget(exe)]
+ targets = targets_d1 + targets_d2
+
+ # Get all IDs and verify they're unique
+ ids = [target.GetGloballyUniqueID() for target in targets]
+ self.assertEqual(
+ len(set(ids)), len(ids), f"IDs should be globally unique: {ids}"
+ )
+ self.assertTrue(
+ all(uid != lldb.LLDB_INVALID_GLOBALLY_UNIQUE_TARGET_ID for uid in ids),
+ "All IDs should be valid",
+ )
+
+ # Verify targets can be found by their IDs in respective debuggers
+ for debugger, target_pair in [
+ (debugger1, targets[:2]),
+ (debugger2, targets[2:]),
+ ]:
+ for target in target_pair:
+ found = debugger.FindTargetByGloballyUniqueID(
+ target.GetGloballyUniqueID()
+ )
+ self.assertTrue(
+ found.IsValid(), "Target should be found by its unique ID"
+ )
+ self.assertEqual(
+ found.GetGloballyUniqueID(), target.GetGloballyUniqueID()
+ )
diff --git a/lldb/test/Shell/SymbolFile/NativePDB/break-by-function.cpp b/lldb/test/Shell/SymbolFile/NativePDB/break-by-function.cpp
index a580d57..d449937 100644
--- a/lldb/test/Shell/SymbolFile/NativePDB/break-by-function.cpp
+++ b/lldb/test/Shell/SymbolFile/NativePDB/break-by-function.cpp
@@ -50,9 +50,9 @@ int main(int argc, char **argv) {
// CHECK: 1: name = 'main', locations = 1
// CHECK: 1.1: where = break-by-function.cpp.tmp.exe`main + {{[0-9]+}}
// CHECK: 2: name = 'OvlGlobalFn', locations = 3
-// CHECK: 2.1: where = break-by-function.cpp.tmp.exe`OvlGlobalFn + {{[0-9]+}}
-// CHECK: 2.2: where = break-by-function.cpp.tmp.exe`OvlGlobalFn
-// CHECK: 2.3: where = break-by-function.cpp.tmp.exe`OvlGlobalFn + {{[0-9]+}}
+// CHECK: 2.1: where = break-by-function.cpp.tmp.exe`int OvlGlobalFn(int) + {{[0-9]+}}
+// CHECK: 2.2: where = break-by-function.cpp.tmp.exe`int OvlGlobalFn(int, int)
+// CHECK: 2.3: where = break-by-function.cpp.tmp.exe`int OvlGlobalFn(int, int, int) + {{[0-9]+}}
// CHECK: 3: name = 'StaticFn', locations = 1
// CHECK: 3.1: where = break-by-function.cpp.tmp.exe`StaticFn + {{[0-9]+}}
// CHECK: 4: name = 'DoesntExist', locations = 0 (pending)
diff --git a/lldb/test/Shell/SymbolFile/NativePDB/break-by-line.cpp b/lldb/test/Shell/SymbolFile/NativePDB/break-by-line.cpp
index 90ac633..3d7de32 100644
--- a/lldb/test/Shell/SymbolFile/NativePDB/break-by-line.cpp
+++ b/lldb/test/Shell/SymbolFile/NativePDB/break-by-line.cpp
@@ -24,4 +24,4 @@ int main(int argc, char **argv) {
// CHECK: (lldb) target create "{{.*}}break-by-line.cpp.tmp.exe"
// CHECK: Current executable set to '{{.*}}break-by-line.cpp.tmp.exe'
// CHECK: (lldb) break set -f break-by-line.cpp -l 15
-// CHECK: Breakpoint 1: where = break-by-line.cpp.tmp.exe`NS::NamespaceFn + {{[0-9]+}} at break-by-line.cpp:15
+// CHECK: Breakpoint 1: where = break-by-line.cpp.tmp.exe`int NS::NamespaceFn(int) + {{[0-9]+}} at break-by-line.cpp:15
diff --git a/lldb/test/Shell/SymbolFile/NativePDB/c-calling-conventions.cpp b/lldb/test/Shell/SymbolFile/NativePDB/c-calling-conventions.cpp
new file mode 100644
index 0000000..d1d0bb0
--- /dev/null
+++ b/lldb/test/Shell/SymbolFile/NativePDB/c-calling-conventions.cpp
@@ -0,0 +1,51 @@
+// clang-format off
+// REQUIRES: lld, (target-x86 || target-x86_64)
+
+// RUN: %build --compiler=clang-cl --arch=32 --nodefaultlib --output=%t-32.exe %s
+// RUN: lldb-test symbols %t-32.exe | FileCheck --check-prefixes CHECK-32,CHECK-BOTH %s
+// RUN: %build --compiler=clang-cl --arch=64 --nodefaultlib --output=%t-64.exe %s
+// RUN: lldb-test symbols %t-64.exe | FileCheck --check-prefixes CHECK-64,CHECK-BOTH %s
+
+extern "C" {
+int FuncCCall() { return 0; }
+int __stdcall FuncStdCall() { return 0; }
+int __fastcall FuncFastCall() { return 0; }
+int __vectorcall FuncVectorCall() { return 0; }
+
+int __cdecl _underscoreCdecl() { return 0; }
+int __stdcall _underscoreStdcall() { return 0; }
+int __fastcall _underscoreFastcall() { return 0; }
+int __vectorcall _underscoreVectorcall() { return 0; }
+}
+
+int main() {
+ FuncCCall();
+ FuncStdCall();
+ FuncFastCall();
+ FuncVectorCall();
+ _underscoreCdecl();
+ _underscoreStdcall();
+ _underscoreFastcall();
+ _underscoreVectorcall();
+ return 0;
+}
+
+// CHECK-BOTH-DAG: Function{{.*}}, demangled = FuncCCall,
+// CHECK-BOTH-DAG: Function{{.*}}, demangled = FuncVectorCall@@0,
+// CHECK-BOTH-DAG: Function{{.*}}, demangled = _underscoreCdecl,
+// CHECK-BOTH-DAG: Function{{.*}}, demangled = _underscoreVectorcall@@0,
+// CHECK-BOTH-DAG: Function{{.*}}, demangled = main,
+
+// __stdcall and __fastcall aren't available on 64 bit
+
+// CHECK-32-DAG: Function{{.*}}, demangled = _FuncStdCall@0,
+// CHECK-64-DAG: Function{{.*}}, demangled = FuncStdCall,
+
+// CHECK-32-DAG: Function{{.*}}, demangled = @FuncFastCall@0,
+// CHECK-64-DAG: Function{{.*}}, demangled = FuncFastCall,
+
+// CHECK-32-DAG: Function{{.*}}, demangled = __underscoreStdcall@0,
+// CHECK-64-DAG: Function{{.*}}, demangled = _underscoreStdcall,
+
+// CHECK-32-DAG: Function{{.*}}, demangled = @_underscoreFastcall@0,
+// CHECK-64-DAG: Function{{.*}}, demangled = _underscoreFastcall,
diff --git a/lldb/test/Shell/SymbolFile/NativePDB/disassembly.cpp b/lldb/test/Shell/SymbolFile/NativePDB/disassembly.cpp
index b3f7b09..05074aa 100644
--- a/lldb/test/Shell/SymbolFile/NativePDB/disassembly.cpp
+++ b/lldb/test/Shell/SymbolFile/NativePDB/disassembly.cpp
@@ -25,7 +25,7 @@ int main(int argc, char **argv) {
// CHECK-NEXT: disassembly.cpp.tmp.exe[{{.*}}] <+12>: mov qword ptr [rsp + 0x28], rdx
// CHECK-NEXT: disassembly.cpp.tmp.exe[{{.*}}] <+17>: mov dword ptr [rsp + 0x24], ecx
// CHECK: ** 15 foo();
-// CHECK: disassembly.cpp.tmp.exe[{{.*}}] <+21>: call {{.*}} ; foo at disassembly.cpp:12
+// CHECK: disassembly.cpp.tmp.exe[{{.*}}] <+21>: call {{.*}} ; int foo(void) at disassembly.cpp:12
// CHECK: ** 16 return 0;
// CHECK-NEXT: 17 }
// CHECK-NEXT: 18
diff --git a/lldb/test/Shell/SymbolFile/NativePDB/find-functions.cpp b/lldb/test/Shell/SymbolFile/NativePDB/find-functions.cpp
index 3ef7a4c..6204cbd 100644
--- a/lldb/test/Shell/SymbolFile/NativePDB/find-functions.cpp
+++ b/lldb/test/Shell/SymbolFile/NativePDB/find-functions.cpp
@@ -148,11 +148,12 @@ int main(int argc, char **argv) {
// FIND-OVERLOAD-BASE-DAG: FuncType: id = {{.*}}, compiler_type = "int (void)"
// FIND-OVERLOAD-BASE-DAG: FuncType: id = {{.*}}, compiler_type = "int (char)"
// FIND-OVERLOAD-BASE-DAG: FuncType: id = {{.*}}, compiler_type = "int (char, int, ...)"
-// FIND-OVERLOAD-BASE-DAG: Function: id = {{.*}}, name = "Class::overloaded_method"
+// FIND-OVERLOAD-BASE-DAG: Function: id = {{.*}}, name = "int Class::overloaded_method(bool)"
// FIND-OVERLOAD-BASE-DAG: FuncType: id = {{.*}}, compiler_type = "_Bool (void)"
// FIND-OVERLOAD-BASE-DAG: FuncType: id = {{.*}}, compiler_type = "_Bool (int)"
// FIND-OVERLOAD-BASE-DAG: FuncType: id = {{.*}}, compiler_type = "int (_Bool)"
-// FIND-OVERLOAD-BASE-DAG: Function: id = {{.*}}, name = "overloaded_method"
+// FIND-OVERLOAD-BASE-DAG: Function: id = {{.*}}, name = "char overloaded_method(void)"
+// FIND-OVERLOAD-BASE-DAG: Function: id = {{.*}}, name = "char overloaded_method(int)"
// FIND-OVERLOAD-BASE-DAG: FuncType: id = {{.*}}, compiler_type = "char (void)"
// FIND-OVERLOAD-BASE-DAG: FuncType: id = {{.*}}, compiler_type = "char (int)"
@@ -160,6 +161,6 @@ int main(int argc, char **argv) {
// FIND-OVERLOAD-METHOD-DAG: Function: id = {{.*}}, name = "{{.*}}Struct::overloaded_method{{.*}}"
// FIND-OVERLOAD-METHOD-DAG: FuncType: id = {{.*}}, compiler_type = "int (void)"
// FIND-OVERLOAD-METHOD-DAG: FuncType: id = {{.*}}, compiler_type = "int (char)"
-// FIND-OVERLOAD-METHOD-DAG: Function: id = {{.*}}, name = "Class::overloaded_method"
+// FIND-OVERLOAD-METHOD-DAG: Function: id = {{.*}}, name = "bool Class::overloaded_method(void)"
// FIND-OVERLOAD-METHOD-DAG: FuncType: id = {{.*}}, compiler_type = "_Bool (void)"
// FIND-OVERLOAD-METHOD-DAG: FuncType: id = {{.*}}, compiler_type = "_Bool (int)"
diff --git a/lldb/test/Shell/SymbolFile/NativePDB/local-variables.cpp b/lldb/test/Shell/SymbolFile/NativePDB/local-variables.cpp
index 44a8dc1..f44a5b9 100644
--- a/lldb/test/Shell/SymbolFile/NativePDB/local-variables.cpp
+++ b/lldb/test/Shell/SymbolFile/NativePDB/local-variables.cpp
@@ -55,7 +55,7 @@ int main(int argc, char **argv) {
// CHECK-NEXT: (lldb) step
// CHECK-NEXT: Process {{.*}} stopped
// CHECK-NEXT: * thread #1, stop reason = step in
-// CHECK-NEXT: frame #0: {{.*}} local-variables.cpp.tmp.exe`Function(Param1=16, Param2='a') at local-variables.cpp:{{.*}}
+// CHECK-NEXT: frame #0: {{.*}} local-variables.cpp.tmp.exe`int Function(Param1=16, Param2='a') at local-variables.cpp:{{.*}}
// CHECK-NEXT: 6
// CHECK-NEXT: 7
// CHECK-NEXT: 8 int Function(int Param1, char Param2) {
@@ -71,7 +71,7 @@ int main(int argc, char **argv) {
// CHECK-NEXT: (lldb) step
// CHECK-NEXT: Process {{.*}} stopped
// CHECK-NEXT: * thread #1, stop reason = step in
-// CHECK-NEXT: frame #0: {{.*}} local-variables.cpp.tmp.exe`Function(Param1=16, Param2='a') at local-variables.cpp:{{.*}}
+// CHECK-NEXT: frame #0: {{.*}} local-variables.cpp.tmp.exe`int Function(Param1=16, Param2='a') at local-variables.cpp:{{.*}}
// CHECK-NEXT: 7
// CHECK-NEXT: 8 int Function(int Param1, char Param2) {
// CHECK-NEXT: 9 unsigned Local1 = Param1 + 1;
@@ -89,7 +89,7 @@ int main(int argc, char **argv) {
// CHECK-NEXT: (lldb) step
// CHECK-NEXT: Process {{.*}} stopped
// CHECK-NEXT: * thread #1, stop reason = step in
-// CHECK-NEXT: frame #0: {{.*}} local-variables.cpp.tmp.exe`Function(Param1=16, Param2='a') at local-variables.cpp:{{.*}}
+// CHECK-NEXT: frame #0: {{.*}} local-variables.cpp.tmp.exe`int Function(Param1=16, Param2='a') at local-variables.cpp:{{.*}}
// CHECK-NEXT: 8 int Function(int Param1, char Param2) {
// CHECK-NEXT: 9 unsigned Local1 = Param1 + 1;
// CHECK-NEXT: 10 char Local2 = Param2 + 1;
@@ -109,7 +109,7 @@ int main(int argc, char **argv) {
// CHECK-NEXT: (lldb) step
// CHECK-NEXT: Process {{.*}} stopped
// CHECK-NEXT: * thread #1, stop reason = step in
-// CHECK-NEXT: frame #0: {{.*}} local-variables.cpp.tmp.exe`Function(Param1=16, Param2='a') at local-variables.cpp:{{.*}}
+// CHECK-NEXT: frame #0: {{.*}} local-variables.cpp.tmp.exe`int Function(Param1=16, Param2='a') at local-variables.cpp:{{.*}}
// CHECK-NEXT: 9 unsigned Local1 = Param1 + 1;
// CHECK-NEXT: 10 char Local2 = Param2 + 1;
// CHECK-NEXT: 11 ++Local1;
@@ -129,7 +129,7 @@ int main(int argc, char **argv) {
// CHECK-NEXT: (lldb) step
// CHECK-NEXT: Process {{.*}} stopped
// CHECK-NEXT: * thread #1, stop reason = step in
-// CHECK-NEXT: frame #0: {{.*}} local-variables.cpp.tmp.exe`Function(Param1=16, Param2='a') at local-variables.cpp:{{.*}}
+// CHECK-NEXT: frame #0: {{.*}} local-variables.cpp.tmp.exe`int Function(Param1=16, Param2='a') at local-variables.cpp:{{.*}}
// CHECK-NEXT: 10 char Local2 = Param2 + 1;
// CHECK-NEXT: 11 ++Local1;
// CHECK-NEXT: 12 ++Local2;
diff --git a/lldb/test/Shell/SymbolFile/NativePDB/stack_unwinding01.cpp b/lldb/test/Shell/SymbolFile/NativePDB/stack_unwinding01.cpp
index 596a826..87eeebe7 100644
--- a/lldb/test/Shell/SymbolFile/NativePDB/stack_unwinding01.cpp
+++ b/lldb/test/Shell/SymbolFile/NativePDB/stack_unwinding01.cpp
@@ -24,19 +24,19 @@ int main(int argc, char **argv) {
// CHECK: (lldb) thread backtrace
// CHECK-NEXT: * thread #1, stop reason = breakpoint 1.1
-// CHECK-NEXT: * frame #0: {{.*}} stack_unwinding01.cpp.tmp.exe`Struct::simple_method(this={{.*}}, a=2, b=2) at stack_unwinding01.cpp:12
+// CHECK-NEXT: * frame #0: {{.*}} stack_unwinding01.cpp.tmp.exe`void Struct::simple_method(this={{.*}}, a=2, b=2) at stack_unwinding01.cpp:12
// CHECK-NEXT: frame #1: {{.*}} stack_unwinding01.cpp.tmp.exe`main(argc={{.*}}, argv={{.*}}) at stack_unwinding01.cpp:20
// CHECK: (lldb) thread backtrace
// CHECK-NEXT: * thread #1, stop reason = breakpoint 1.1
-// CHECK-NEXT: * frame #0: {{.*}} stack_unwinding01.cpp.tmp.exe`Struct::simple_method(this={{.*}}, a=3, b=2) at stack_unwinding01.cpp:12
-// CHECK-NEXT: frame #1: {{.*}} stack_unwinding01.cpp.tmp.exe`Struct::simple_method(this={{.*}}, a=2, b=2) at stack_unwinding01.cpp:12
+// CHECK-NEXT: * frame #0: {{.*}} stack_unwinding01.cpp.tmp.exe`void Struct::simple_method(this={{.*}}, a=3, b=2) at stack_unwinding01.cpp:12
+// CHECK-NEXT: frame #1: {{.*}} stack_unwinding01.cpp.tmp.exe`void Struct::simple_method(this={{.*}}, a=2, b=2) at stack_unwinding01.cpp:12
// CHECK-NEXT: frame #2: {{.*}} stack_unwinding01.cpp.tmp.exe`main(argc={{.*}}, argv={{.*}}) at stack_unwinding01.cpp:20
// CHECK: (lldb) thread backtrace
// CHECK-NEXT: * thread #1, stop reason = breakpoint 1.1
-// CHECK-NEXT: * frame #0: {{.*}} stack_unwinding01.cpp.tmp.exe`Struct::simple_method(this={{.*}}, a=4, b=2) at stack_unwinding01.cpp:12
-// CHECK-NEXT: frame #1: {{.*}} stack_unwinding01.cpp.tmp.exe`Struct::simple_method(this={{.*}}, a=3, b=2) at stack_unwinding01.cpp:12
-// CHECK-NEXT: frame #2: {{.*}} stack_unwinding01.cpp.tmp.exe`Struct::simple_method(this={{.*}}, a=2, b=2) at stack_unwinding01.cpp:12
+// CHECK-NEXT: * frame #0: {{.*}} stack_unwinding01.cpp.tmp.exe`void Struct::simple_method(this={{.*}}, a=4, b=2) at stack_unwinding01.cpp:12
+// CHECK-NEXT: frame #1: {{.*}} stack_unwinding01.cpp.tmp.exe`void Struct::simple_method(this={{.*}}, a=3, b=2) at stack_unwinding01.cpp:12
+// CHECK-NEXT: frame #2: {{.*}} stack_unwinding01.cpp.tmp.exe`void Struct::simple_method(this={{.*}}, a=2, b=2) at stack_unwinding01.cpp:12
// CHECK-NEXT: frame #3: {{.*}} stack_unwinding01.cpp.tmp.exe`main(argc={{.*}}, argv={{.*}}) at stack_unwinding01.cpp:20
diff --git a/lldb/test/Shell/SymbolFile/PDB/function-nested-block.test b/lldb/test/Shell/SymbolFile/PDB/function-nested-block.test
index 9057d01..4a2355b 100644
--- a/lldb/test/Shell/SymbolFile/PDB/function-nested-block.test
+++ b/lldb/test/Shell/SymbolFile/PDB/function-nested-block.test
@@ -4,7 +4,7 @@ RUN: lldb-test symbols -find=function -file FunctionNestedBlockTest.cpp -line 4
RUN: lldb-test symbols -find=block -file FunctionNestedBlockTest.cpp -line 4 %t.exe | FileCheck --check-prefix=CHECK-BLOCK %s
CHECK-FUNCTION: Found 1 functions:
-CHECK-FUNCTION: name = "{{.*}}", mangled = "{{_?}}main"
+CHECK-FUNCTION: name = "main"
CHECK-BLOCK: Found 1 blocks:
CHECK-BLOCK: Blocks: id = {{.*}}, range = {{.*}}
diff --git a/lldb/test/Shell/SymbolFile/PDB/variables.test b/lldb/test/Shell/SymbolFile/PDB/variables.test
index 970d714..cb761de 100644
--- a/lldb/test/Shell/SymbolFile/PDB/variables.test
+++ b/lldb/test/Shell/SymbolFile/PDB/variables.test
@@ -42,7 +42,7 @@ GLOBALS-DAG: Variable{{.*}}, name = "g_Const"
GLOBALS-SAME: scope = ??? (2)
GLOBALS: Function
-FUNC-F: Function{{.*}}, {{mangled = \?f@@YAHHH@Z|demangled = f}}
+FUNC-F: Function{{.*}}, mangled = ?f@@YAHHH@Z
FUNC-F-NEXT: Block
FUNC-F-NEXT: Variable{{.*}}, name = "var_arg1"
FUNC-F-SAME: scope = parameter
@@ -64,14 +64,14 @@ FUNC-MAIN-SAME: scope = local
FUNC-MAIN-NEXT: Variable{{.*}}, name = "a"
FUNC-MAIN-SAME: scope = local
-FUNC-CONSTRUCTOR: Function{{.*}}, {{(de)?}}mangled = {{.*}}Class::Class{{.*}}
+FUNC-CONSTRUCTOR: Function{{.*}}, {{mangled = \?\?0Class@@QEAA@H@Z|demangled = .*Class::Class}}
FUNC-CONSTRUCTOR-NEXT: Block
FUNC-CONSTRUCTOR-NEXT: Variable{{.*}}, name = "this"
FUNC-CONSTRUCTOR-SAME: scope = parameter
FUNC-CONSTRUCTOR-NEXT: Variable{{.*}}, name = "a"
FUNC-CONSTRUCTOR-SAME: scope = parameter
-FUNC-MEMBER: Function{{.*}}, {{(de)?}}mangled = {{.*}}{{(Class::)?}}Func{{.*}}
+FUNC-MEMBER: Function{{.*}}, {{mangled = \?Func@Class@@QEAAXXZ|demangled = .*Class::Func}}
FUNC-MEMBER-NEXT: Block
FUNC-MEMBER-NEXT: Variable{{.*}}, name = "this"
FUNC-MEMBER-SAME: scope = parameter
diff --git a/lldb/tools/debugserver/source/RNBRemote.cpp b/lldb/tools/debugserver/source/RNBRemote.cpp
index 434e9cf..b06c6bf 100644
--- a/lldb/tools/debugserver/source/RNBRemote.cpp
+++ b/lldb/tools/debugserver/source/RNBRemote.cpp
@@ -93,11 +93,34 @@ static const std::string JSON_ASYNC_TYPE_KEY_NAME("type");
std::setfill(' ') << std::setw((iword_idx)) << ""
#define INDENT_WITH_TABS(iword_idx) \
std::setfill('\t') << std::setw((iword_idx)) << ""
-// Class to handle communications via gdb remote protocol.
-// Prototypes
+// If `ch` is a meta character as per the binary packet convention in the
+// gdb-remote protocol, quote it and write it into `stream`, otherwise write it
+// as is.
+static void binary_encode_char(std::ostringstream &stream, char ch) {
+ if (ch == '#' || ch == '$' || ch == '}' || ch == '*') {
+ stream.put('}');
+ stream.put(ch ^ 0x20);
+ } else {
+ stream.put(ch);
+ }
+}
-static std::string binary_encode_string(const std::string &s);
+// Equivalent to calling binary_encode_char for every element of `data`.
+static void binary_encode_data_vector(std::ostringstream &stream,
+ std::vector<uint8_t> data) {
+ for (auto ch : data)
+ binary_encode_char(stream, ch);
+}
+
+// Quote any meta characters in a std::string as per the binary
+// packet convention in the gdb-remote protocol.
+static std::string binary_encode_string(const std::string &s) {
+ std::ostringstream stream;
+ for (char ch : s)
+ binary_encode_char(stream, ch);
+ return stream.str();
+}
// Decode a single hex character and return the hex value as a number or
// -1 if "ch" is not a hex character.
@@ -139,16 +162,16 @@ static std::string decode_hex_ascii_string(const char *p,
return arg;
}
-uint64_t decode_uint64(const char *p, int base, char **end = nullptr,
- uint64_t fail_value = 0) {
+static uint64_t decode_uint64(const char *p, int base, char **end = nullptr,
+ uint64_t fail_value = 0) {
nub_addr_t addr = strtoull(p, end, 16);
if (addr == 0 && errno != 0)
return fail_value;
return addr;
}
-void append_hex_value(std::ostream &ostrm, const void *buf, size_t buf_size,
- bool swap) {
+static void append_hex_value(std::ostream &ostrm, const void *buf,
+ size_t buf_size, bool swap) {
int i;
const uint8_t *p = (const uint8_t *)buf;
if (swap) {
@@ -160,7 +183,7 @@ void append_hex_value(std::ostream &ostrm, const void *buf, size_t buf_size,
}
}
-std::string cstring_to_asciihex_string(const char *str) {
+static std::string cstring_to_asciihex_string(const char *str) {
std::string hex_str;
hex_str.reserve(strlen(str) * 2);
while (str && *str) {
@@ -172,7 +195,8 @@ std::string cstring_to_asciihex_string(const char *str) {
return hex_str;
}
-void append_hexified_string(std::ostream &ostrm, const std::string &string) {
+static void append_hexified_string(std::ostream &ostrm,
+ const std::string &string) {
size_t string_size = string.size();
const char *string_buf = string.c_str();
for (size_t i = 0; i < string_size; i++) {
@@ -1027,8 +1051,6 @@ rnb_err_t RNBRemote::HandleAsyncPacket(PacketEnum *type) {
rnb_err_t RNBRemote::HandleReceivedPacket(PacketEnum *type) {
static DNBTimer g_packetTimer(true);
- // DNBLogThreadedIf (LOG_RNB_REMOTE, "%8u RNBRemote::%s",
- // (uint32_t)m_comm.Timer().ElapsedMicroSeconds(true), __FUNCTION__);
rnb_err_t err = rnb_err;
std::string packet_data;
RNBRemote::Packet packet_info;
@@ -1284,8 +1306,7 @@ static cpu_type_t best_guess_cpu_type() {
LEN is the number of bytes to be processed. If a character is escaped,
it is 2 characters for LEN. A LEN of -1 means decode-until-nul-byte
(end of string). */
-
-std::vector<uint8_t> decode_binary_data(const char *str, size_t len) {
+static std::vector<uint8_t> decode_binary_data(const char *str, size_t len) {
std::vector<uint8_t> bytes;
if (len == 0) {
return bytes;
@@ -1304,31 +1325,10 @@ std::vector<uint8_t> decode_binary_data(const char *str, size_t len) {
return bytes;
}
-// Quote any meta characters in a std::string as per the binary
-// packet convention in the gdb-remote protocol.
-
-static std::string binary_encode_string(const std::string &s) {
- std::string output;
- const size_t s_size = s.size();
- const char *s_chars = s.c_str();
-
- for (size_t i = 0; i < s_size; i++) {
- unsigned char ch = *(s_chars + i);
- if (ch == '#' || ch == '$' || ch == '}' || ch == '*') {
- output.push_back('}'); // 0x7d
- output.push_back(ch ^ 0x20);
- } else {
- output.push_back(ch);
- }
- }
- return output;
-}
-
// If the value side of a key-value pair in JSON is a string,
// and that string has a " character in it, the " character must
// be escaped.
-
-std::string json_string_quote_metachars(const std::string &s) {
+static std::string json_string_quote_metachars(const std::string &s) {
if (s.find('"') == std::string::npos)
return s;
@@ -1462,15 +1462,6 @@ bool RNBRemote::InitializeRegisters(bool force) {
}
}
- // for (auto &reg_entry: g_dynamic_register_map)
- // {
- // DNBLogThreaded("%4i: size = %3u, pseudo = %i, name = %s",
- // reg_entry.offset,
- // reg_entry.nub_info.size,
- // reg_entry.nub_info.value_regs != NULL,
- // reg_entry.nub_info.name);
- // }
-
g_reg_entries = g_dynamic_register_map.data();
g_num_reg_entries = g_dynamic_register_map.size();
}
@@ -1719,7 +1710,7 @@ rnb_err_t RNBRemote::HandlePacket_qThreadExtraInfo(const char *p) {
return SendPacket("");
}
-const char *k_space_delimiters = " \t";
+static const char *k_space_delimiters = " \t";
static void skip_spaces(std::string &line) {
if (!line.empty()) {
size_t space_pos = line.find_first_not_of(k_space_delimiters);
@@ -2024,7 +2015,7 @@ rnb_err_t RNBRemote::HandlePacket_qRegisterInfo(const char *p) {
QSetLogging:bitmask=LOG_ALL;mode=asl;
*/
-rnb_err_t set_logging(const char *p) {
+static rnb_err_t set_logging(const char *p) {
int bitmask = 0;
while (p && *p != '\0') {
if (strncmp(p, "bitmask=", sizeof("bitmask=") - 1) == 0) {
@@ -2568,11 +2559,10 @@ rnb_err_t RNBRemote::HandlePacket_QSetProcessEvent(const char *p) {
// If a fail_value is provided, a correct-length reply is always provided,
// even if the register cannot be read right now on this thread.
-bool register_value_in_hex_fixed_width(std::ostream &ostrm, nub_process_t pid,
- nub_thread_t tid,
- const register_map_entry_t *reg,
- const DNBRegisterValue *reg_value_ptr,
- std::optional<uint8_t> fail_value) {
+static bool register_value_in_hex_fixed_width(
+ std::ostream &ostrm, nub_process_t pid, nub_thread_t tid,
+ const register_map_entry_t *reg, const DNBRegisterValue *reg_value_ptr,
+ std::optional<uint8_t> fail_value) {
if (reg != NULL) {
std::unique_ptr<DNBRegisterValue> reg_value =
std::make_unique<DNBRegisterValue>();
@@ -2599,7 +2589,7 @@ bool register_value_in_hex_fixed_width(std::ostream &ostrm, nub_process_t pid,
return false;
}
-void debugserver_regnum_with_fixed_width_hex_register_value(
+static void debugserver_regnum_with_fixed_width_hex_register_value(
std::ostream &ostrm, nub_process_t pid, nub_thread_t tid,
const register_map_entry_t *reg, const DNBRegisterValue *reg_value_ptr,
std::optional<uint8_t> fail_value) {
@@ -3216,21 +3206,9 @@ rnb_err_t RNBRemote::HandlePacket_x(const char *p) {
return SendErrorPacket("E80");
}
- std::vector<uint8_t> buf_quoted;
- buf_quoted.reserve(bytes_read + 30);
- for (nub_size_t i = 0; i < bytes_read; i++) {
- if (buf[i] == '#' || buf[i] == '$' || buf[i] == '}' || buf[i] == '*') {
- buf_quoted.push_back(0x7d);
- buf_quoted.push_back(buf[i] ^ 0x20);
- } else {
- buf_quoted.push_back(buf[i]);
- }
- }
- length = buf_quoted.size();
-
+ buf.resize(bytes_read);
std::ostringstream ostrm;
- for (unsigned long i = 0; i < length; i++)
- ostrm << buf_quoted[i];
+ binary_encode_data_vector(ostrm, buf);
return SendPacket(ostrm.str());
}
@@ -4902,8 +4880,8 @@ rnb_err_t RNBRemote::HandlePacket_qHostInfo(const char *p) {
return SendPacket(strm.str());
}
-void XMLElementStart(std::ostringstream &s, uint32_t indent, const char *name,
- bool has_attributes) {
+static void XMLElementStart(std::ostringstream &s, uint32_t indent,
+ const char *name, bool has_attributes) {
if (indent)
s << INDENT_WITH_SPACES(indent);
s << '<' << name;
@@ -4911,43 +4889,22 @@ void XMLElementStart(std::ostringstream &s, uint32_t indent, const char *name,
s << '>' << std::endl;
}
-void XMLElementStartEndAttributes(std::ostringstream &s, bool empty) {
+static void XMLElementStartEndAttributes(std::ostringstream &s, bool empty) {
if (empty)
s << '/';
s << '>' << std::endl;
}
-void XMLElementEnd(std::ostringstream &s, uint32_t indent, const char *name) {
+static void XMLElementEnd(std::ostringstream &s, uint32_t indent,
+ const char *name) {
if (indent)
s << INDENT_WITH_SPACES(indent);
s << '<' << '/' << name << '>' << std::endl;
}
-void XMLElementWithStringValue(std::ostringstream &s, uint32_t indent,
- const char *name, const char *value,
- bool close = true) {
- if (value) {
- if (indent)
- s << INDENT_WITH_SPACES(indent);
- s << '<' << name << '>' << value;
- if (close)
- XMLElementEnd(s, 0, name);
- }
-}
-
-void XMLElementWithUnsignedValue(std::ostringstream &s, uint32_t indent,
- const char *name, uint64_t value,
- bool close = true) {
- if (indent)
- s << INDENT_WITH_SPACES(indent);
-
- s << '<' << name << '>' << DECIMAL << value;
- if (close)
- XMLElementEnd(s, 0, name);
-}
-
-void XMLAttributeString(std::ostringstream &s, const char *name,
- const char *value, const char *default_value = NULL) {
+static void XMLAttributeString(std::ostringstream &s, const char *name,
+ const char *value,
+ const char *default_value = NULL) {
if (value) {
if (default_value && strcmp(value, default_value) == 0)
return; // No need to emit the attribute because it matches the default
@@ -4956,15 +4913,16 @@ void XMLAttributeString(std::ostringstream &s, const char *name,
}
}
-void XMLAttributeUnsignedDecimal(std::ostringstream &s, const char *name,
- uint64_t value) {
+static void XMLAttributeUnsignedDecimal(std::ostringstream &s, const char *name,
+ uint64_t value) {
s << ' ' << name << "=\"" << DECIMAL << value << "\"";
}
-void GenerateTargetXMLRegister(std::ostringstream &s, const uint32_t reg_num,
- nub_size_t num_reg_sets,
- const DNBRegisterSetInfo *reg_set_info,
- const register_map_entry_t &reg) {
+static void GenerateTargetXMLRegister(std::ostringstream &s,
+ const uint32_t reg_num,
+ nub_size_t num_reg_sets,
+ const DNBRegisterSetInfo *reg_set_info,
+ const register_map_entry_t &reg) {
const char *default_lldb_encoding = "uint";
const char *lldb_encoding = default_lldb_encoding;
const char *gdb_group = "general";
@@ -5135,7 +5093,7 @@ void GenerateTargetXMLRegister(std::ostringstream &s, const uint32_t reg_num,
XMLElementStartEndAttributes(s, true);
}
-void GenerateTargetXMLRegisters(std::ostringstream &s) {
+static void GenerateTargetXMLRegisters(std::ostringstream &s) {
nub_size_t num_reg_sets = 0;
const DNBRegisterSetInfo *reg_sets = DNBGetRegisterSetInfo(&num_reg_sets);
@@ -5174,7 +5132,7 @@ static const char *g_target_xml_footer = "</target>";
static std::string g_target_xml;
-void UpdateTargetXML() {
+static void UpdateTargetXML() {
std::ostringstream s;
s << g_target_xml_header << std::endl;
@@ -5309,8 +5267,9 @@ rnb_err_t RNBRemote::HandlePacket_jGetDyldProcessState(const char *p) {
// a one-level-deep JSON dictionary of key-value pairs. e.g.
// jThreadExtendedInfo:{"plo_pthread_tsd_base_address_offset":0,"plo_pthread_tsd_base_offset":224,"plo_pthread_tsd_entry_size":8,"thread":144305}]
//
-uint64_t get_integer_value_for_key_name_from_json(const char *key,
- const char *json_string) {
+static uint64_t
+get_integer_value_for_key_name_from_json(const char *key,
+ const char *json_string) {
uint64_t retval = INVALID_NUB_ADDRESS;
std::string key_with_quotes = "\"";
key_with_quotes += key;
@@ -5346,9 +5305,9 @@ uint64_t get_integer_value_for_key_name_from_json(const char *key,
// Returns true if it was able to find the key name, and sets the 'value'
// argument to the value found.
-bool get_boolean_value_for_key_name_from_json(const char *key,
- const char *json_string,
- bool &value) {
+static bool get_boolean_value_for_key_name_from_json(const char *key,
+ const char *json_string,
+ bool &value) {
std::string key_with_quotes = "\"";
key_with_quotes += key;
key_with_quotes += "\"";
@@ -5385,7 +5344,7 @@ bool get_boolean_value_for_key_name_from_json(const char *key,
// Returns true if it was able to find the key name, false if it did not.
// "ints" will have all integers found in the array appended to it.
-bool get_array_of_ints_value_for_key_name_from_json(
+static bool get_array_of_ints_value_for_key_name_from_json(
const char *key, const char *json_string, std::vector<uint64_t> &ints) {
std::string key_with_quotes = "\"";
key_with_quotes += key;
diff --git a/lldb/unittests/Host/MainLoopTest.cpp b/lldb/unittests/Host/MainLoopTest.cpp
index 0bc291c..ae16d02 100644
--- a/lldb/unittests/Host/MainLoopTest.cpp
+++ b/lldb/unittests/Host/MainLoopTest.cpp
@@ -424,9 +424,9 @@ TEST_F(MainLoopTest, ManyPendingCallbacks) {
TEST_F(MainLoopTest, CallbackWithTimeout) {
MainLoop loop;
+ auto start = std::chrono::steady_clock::now();
loop.AddCallback([](MainLoopBase &loop) { loop.RequestTermination(); },
std::chrono::seconds(2));
- auto start = std::chrono::steady_clock::now();
ASSERT_THAT_ERROR(loop.Run().takeError(), llvm::Succeeded());
EXPECT_GE(std::chrono::steady_clock::now() - start, std::chrono::seconds(2));
}