diff options
Diffstat (limited to 'lldb')
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 ®_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 ®) { +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 ®) { 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)); } |