From 4da8fa45a0968a1f98010777d3731a921431ee55 Mon Sep 17 00:00:00 2001 From: Med Ismail Bennani Date: Fri, 11 Sep 2020 20:09:44 +0200 Subject: [PATCH] [lldb/API] Add Breakpoint::SerializeToStructuredData to SBAPI This patch adds a way to fetch breakpoint metadatas as a serialized `Structured` Data format (JSON). This can be used by IDEs to update their UI when a breakpoint is set or modified from the console. rdar://11013798 Differential Revision: https://reviews.llvm.org/D87491 Signed-off-by: Med Ismail Bennani --- lldb/bindings/interface/SBBreakpoint.i | 2 ++ lldb/include/lldb/API/SBBreakpoint.h | 4 ++- lldb/source/API/SBBreakpoint.cpp | 19 +++++++++- .../serialize/TestBreakpointSerialization.py | 36 +++++++++++++++++++ 4 files changed, 59 insertions(+), 2 deletions(-) diff --git a/lldb/bindings/interface/SBBreakpoint.i b/lldb/bindings/interface/SBBreakpoint.i index a2d747db0bf6..e386ace9dee8 100644 --- a/lldb/bindings/interface/SBBreakpoint.i +++ b/lldb/bindings/interface/SBBreakpoint.i @@ -234,6 +234,8 @@ public: SBError AddLocation(SBAddress &address); + SBStructuredData SBBreakpoint::SerializeToStructuredData(); + static bool EventIsBreakpointEvent (const lldb::SBEvent &event); diff --git a/lldb/include/lldb/API/SBBreakpoint.h b/lldb/include/lldb/API/SBBreakpoint.h index c9a52fcacf1a..39a021145fb7 100644 --- a/lldb/include/lldb/API/SBBreakpoint.h +++ b/lldb/include/lldb/API/SBBreakpoint.h @@ -140,7 +140,9 @@ public: // Can only be called from a ScriptedBreakpointResolver... SBError AddLocation(SBAddress &address); - + + SBStructuredData SerializeToStructuredData(); + private: friend class SBBreakpointList; friend class SBBreakpointLocation; diff --git a/lldb/source/API/SBBreakpoint.cpp b/lldb/source/API/SBBreakpoint.cpp index eb75bf8b33f4..96b77bd8539e 100644 --- a/lldb/source/API/SBBreakpoint.cpp +++ b/lldb/source/API/SBBreakpoint.cpp @@ -575,7 +575,22 @@ SBError SBBreakpoint::AddLocation(SBAddress &address) { return LLDB_RECORD_RESULT(error); } -void SBBreakpoint ::SetCallback(SBBreakpointHitCallback callback, void *baton) { +SBStructuredData SBBreakpoint::SerializeToStructuredData() { + LLDB_RECORD_METHOD_NO_ARGS(lldb::SBStructuredData, SBBreakpoint, + SerializeToStructuredData); + + SBStructuredData data; + BreakpointSP bkpt_sp = GetSP(); + + if (!bkpt_sp) + return LLDB_RECORD_RESULT(data); + + StructuredData::ObjectSP bkpt_dict = bkpt_sp->SerializeToStructuredData(); + data.m_impl_up->SetObjectSP(bkpt_dict); + return LLDB_RECORD_RESULT(data); +} + +void SBBreakpoint::SetCallback(SBBreakpointHitCallback callback, void *baton) { LLDB_RECORD_DUMMY(void, SBBreakpoint, SetCallback, (lldb::SBBreakpointHitCallback, void *), callback, baton); @@ -1017,6 +1032,8 @@ void RegisterMethods(Registry &R) { (lldb::SBStream &, bool)); LLDB_REGISTER_METHOD(lldb::SBError, SBBreakpoint, AddLocation, (lldb::SBAddress &)); + LLDB_REGISTER_METHOD(lldb::SBStructuredData, SBBreakpoint, + SerializeToStructuredData, ()); LLDB_REGISTER_METHOD(void, SBBreakpoint, SetScriptCallbackFunction, (const char *)); LLDB_REGISTER_METHOD(lldb::SBError, SBBreakpoint, SetScriptCallbackFunction, diff --git a/lldb/test/API/functionalities/breakpoint/serialize/TestBreakpointSerialization.py b/lldb/test/API/functionalities/breakpoint/serialize/TestBreakpointSerialization.py index 6a3f40ff3a35..b26af93525dc 100644 --- a/lldb/test/API/functionalities/breakpoint/serialize/TestBreakpointSerialization.py +++ b/lldb/test/API/functionalities/breakpoint/serialize/TestBreakpointSerialization.py @@ -3,6 +3,7 @@ Test breakpoint serialization. """ import os +import json import lldb from lldbsuite.test.decorators import * from lldbsuite.test.lldbtest import * @@ -56,6 +57,41 @@ class BreakpointSerialization(TestBase): self.setup_targets_and_cleanup() self.do_check_extra_args() + def test_structured_data_serialization(self): + target = self.dbg.GetDummyTarget() + self.assertTrue(target.IsValid(), VALID_TARGET) + + interpreter = self.dbg.GetCommandInterpreter() + result = lldb.SBCommandReturnObject() + interpreter.HandleCommand("br set -f foo -l 42", result) + result = lldb.SBCommandReturnObject() + interpreter.HandleCommand("br set -c 'argc == 1' -n main", result) + + bkp1 = target.GetBreakpointAtIndex(0) + self.assertTrue(bkp1.IsValid(), VALID_BREAKPOINT) + stream = lldb.SBStream() + sd = bkp1.SerializeToStructuredData() + sd.GetAsJSON(stream) + serialized_data = json.loads(stream.GetData()) + self.assertEqual(serialized_data["Breakpoint"]["BKPTResolver"]["Options"]["FileName"], "foo") + self.assertEqual(serialized_data["Breakpoint"]["BKPTResolver"]["Options"]["LineNumber"], 42) + + bkp2 = target.GetBreakpointAtIndex(1) + self.assertTrue(bkp2.IsValid(), VALID_BREAKPOINT) + stream = lldb.SBStream() + sd = bkp2.SerializeToStructuredData() + sd.GetAsJSON(stream) + serialized_data = json.loads(stream.GetData()) + self.assertIn("main", serialized_data["Breakpoint"]["BKPTResolver"]["Options"]["SymbolNames"]) + self.assertEqual(serialized_data["Breakpoint"]["BKPTOptions"]["ConditionText"],"argc == 1") + + invalid_bkp = lldb.SBBreakpoint() + self.assertFalse(invalid_bkp.IsValid(), "Breakpoint should not be valid.") + stream = lldb.SBStream() + sd = invalid_bkp.SerializeToStructuredData() + sd.GetAsJSON(stream) + self.assertFalse(stream.GetData(), "Invalid breakpoint should have an empty structured data") + def setup_targets_and_cleanup(self): def cleanup (): self.RemoveTempFile(self.bkpts_file_path)