This revision was automatically updated to reflect the committed changes.
Closed by commit rG4bc86ae83e95: [lldb-vscode] Send Selected Statistics Dump in 
Terminated Event (authored by kusmour).
Herald added a project: LLDB.
Herald added a subscriber: lldb-commits.

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D137665/new/

https://reviews.llvm.org/D137665

Files:
  lldb/packages/Python/lldbsuite/test/tools/lldb-vscode/vscode.py
  lldb/test/API/tools/lldb-vscode/terminated-event/Makefile
  lldb/test/API/tools/lldb-vscode/terminated-event/TestVSCode_terminatedEvent.py
  lldb/test/API/tools/lldb-vscode/terminated-event/foo.cpp
  lldb/test/API/tools/lldb-vscode/terminated-event/foo.h
  lldb/test/API/tools/lldb-vscode/terminated-event/main.cpp
  lldb/tools/lldb-vscode/JSONUtils.cpp
  lldb/tools/lldb-vscode/JSONUtils.h
  lldb/tools/lldb-vscode/lldb-vscode.cpp

Index: lldb/tools/lldb-vscode/lldb-vscode.cpp
===================================================================
--- lldb/tools/lldb-vscode/lldb-vscode.cpp
+++ lldb/tools/lldb-vscode/lldb-vscode.cpp
@@ -204,7 +204,7 @@
     g_vsc.sent_terminated_event = true;
     g_vsc.RunTerminateCommands();
     // Send a "terminated" event
-    llvm::json::Object event(CreateEventObject("terminated"));
+    llvm::json::Object event(CreateTerminatedEventObject());
     g_vsc.SendJSON(llvm::json::Value(std::move(event)));
   }
 }
@@ -2949,7 +2949,7 @@
       const uint32_t addr_size = g_vsc.target.GetProcess().GetAddressByteSize();
       lldb::SBValue reg_set = g_vsc.variables.registers.GetValueAtIndex(0);
       const uint32_t num_regs = reg_set.GetNumChildren();
-      for (uint32_t reg_idx=0; reg_idx<num_regs; ++reg_idx) {
+      for (uint32_t reg_idx = 0; reg_idx < num_regs; ++reg_idx) {
         lldb::SBValue reg = reg_set.GetChildAtIndex(reg_idx);
         const lldb::Format format = reg.GetFormat();
         if (format == lldb::eFormatDefault || format == lldb::eFormatHex) {
Index: lldb/tools/lldb-vscode/JSONUtils.h
===================================================================
--- lldb/tools/lldb-vscode/JSONUtils.h
+++ lldb/tools/lldb-vscode/JSONUtils.h
@@ -485,6 +485,12 @@
                                   llvm::StringRef debug_adaptor_path,
                                   llvm::StringRef comm_file);
 
+/// Create a "Terminated" JSON object that contains statistics
+///
+/// \return
+///     A body JSON object with debug info and breakpoint info
+llvm::json::Object CreateTerminatedEventObject();
+
 /// Convert a given JSON object to a string.
 std::string JSONToString(const llvm::json::Value &json);
 
Index: lldb/tools/lldb-vscode/JSONUtils.cpp
===================================================================
--- lldb/tools/lldb-vscode/JSONUtils.cpp
+++ lldb/tools/lldb-vscode/JSONUtils.cpp
@@ -19,6 +19,8 @@
 #include "lldb/API/SBBreakpoint.h"
 #include "lldb/API/SBBreakpointLocation.h"
 #include "lldb/API/SBDeclaration.h"
+#include "lldb/API/SBStringList.h"
+#include "lldb/API/SBStructuredData.h"
 #include "lldb/API/SBValue.h"
 #include "lldb/Host/PosixApi.h"
 
@@ -1140,6 +1142,73 @@
   return reverse_request;
 }
 
+// Keep all the top level items from the statistics dump, except for the
+// "modules" array. It can be huge and cause delay
+// Array and dictionary value will return as <key, JSON string> pairs
+void FilterAndGetValueForKey(const lldb::SBStructuredData data, const char *key,
+                             llvm::json::Object &out) {
+  lldb::SBStructuredData value = data.GetValueForKey(key);
+  std::string key_utf8 = llvm::json::fixUTF8(key);
+  if (strcmp(key, "modules") == 0)
+    return;
+  switch (value.GetType()) {
+  case lldb::eStructuredDataTypeFloat:
+    out.try_emplace(key_utf8, value.GetFloatValue());
+    break;
+  case lldb::eStructuredDataTypeInteger:
+    out.try_emplace(key_utf8, value.GetIntegerValue());
+    break;
+  case lldb::eStructuredDataTypeArray: {
+    lldb::SBStream contents;
+    value.GetAsJSON(contents);
+    out.try_emplace(key_utf8, llvm::json::fixUTF8(contents.GetData()));
+  } break;
+  case lldb::eStructuredDataTypeBoolean:
+    out.try_emplace(key_utf8, value.GetBooleanValue());
+    break;
+  case lldb::eStructuredDataTypeString: {
+    // Get the string size before reading
+    const size_t str_length = value.GetStringValue(nullptr, 0);
+    std::string str(str_length + 1, 0);
+    value.GetStringValue(&str[0], str_length);
+    out.try_emplace(key_utf8, llvm::json::fixUTF8(str));
+  } break;
+  case lldb::eStructuredDataTypeDictionary: {
+    lldb::SBStream contents;
+    value.GetAsJSON(contents);
+    out.try_emplace(key_utf8, llvm::json::fixUTF8(contents.GetData()));
+  } break;
+  case lldb::eStructuredDataTypeNull:
+  case lldb::eStructuredDataTypeGeneric:
+  case lldb::eStructuredDataTypeInvalid:
+    break;
+  }
+}
+
+void addStatistic(llvm::json::Object &event) {
+  lldb::SBStructuredData statistics = g_vsc.target.GetStatistics();
+  bool is_dictionary =
+      statistics.GetType() == lldb::eStructuredDataTypeDictionary;
+  if (!is_dictionary)
+    return;
+  llvm::json::Object stats_body;
+
+  lldb::SBStringList keys;
+  if (!statistics.GetKeys(keys))
+    return;
+  for (size_t i = 0; i < keys.GetSize(); i++) {
+    const char *key = keys.GetStringAtIndex(i);
+    FilterAndGetValueForKey(statistics, key, stats_body);
+  }
+  event.try_emplace("statistics", std::move(stats_body));
+}
+
+llvm::json::Object CreateTerminatedEventObject() {
+  llvm::json::Object event(CreateEventObject("terminated"));
+  addStatistic(event);
+  return event;
+}
+
 std::string JSONToString(const llvm::json::Value &json) {
   std::string data;
   llvm::raw_string_ostream os(data);
Index: lldb/test/API/tools/lldb-vscode/terminated-event/main.cpp
===================================================================
--- /dev/null
+++ lldb/test/API/tools/lldb-vscode/terminated-event/main.cpp
@@ -0,0 +1,8 @@
+#include <iostream>
+#include "foo.h"
+
+int main(int argc, char const *argv[]) {
+  std::cout << "Hello World!" << std::endl; // main breakpoint 1
+  foo();
+  return 0;
+}
Index: lldb/test/API/tools/lldb-vscode/terminated-event/foo.h
===================================================================
--- /dev/null
+++ lldb/test/API/tools/lldb-vscode/terminated-event/foo.h
@@ -0,0 +1 @@
+int foo();
Index: lldb/test/API/tools/lldb-vscode/terminated-event/foo.cpp
===================================================================
--- /dev/null
+++ lldb/test/API/tools/lldb-vscode/terminated-event/foo.cpp
@@ -0,0 +1,3 @@
+int foo() {
+    return 12;
+}
Index: lldb/test/API/tools/lldb-vscode/terminated-event/TestVSCode_terminatedEvent.py
===================================================================
--- /dev/null
+++ lldb/test/API/tools/lldb-vscode/terminated-event/TestVSCode_terminatedEvent.py
@@ -0,0 +1,64 @@
+"""
+Test lldb-vscode terminated event
+"""
+
+import vscode
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+import lldbvscode_testcase
+import re
+import json
+
+class TestVSCode_terminatedEvent(lldbvscode_testcase.VSCodeTestCaseBase):
+
+    @skipIfWindows
+    @skipIfRemote
+    def test_terminated_event(self):
+        '''
+            Terminated Event
+            Now contains the statistics of a debug session:
+            metatdata:
+                totalDebugInfoByteSize > 0
+                totalDebugInfoEnabled > 0
+                totalModuleCountHasDebugInfo > 0
+                ...
+            targetInfo:
+                totalBreakpointResolveTime > 0
+            breakpoints:
+                recognize function breakpoint
+                recognize source line breakpoint
+            It should contains the breakpoints info: function bp & source line bp
+        '''
+
+        program_basename = "a.out.stripped"
+        program = self.getBuildArtifact(program_basename)
+        self.build_and_launch(program)
+        # Set breakpoints
+        functions = ['foo']
+        breakpoint_ids = self.set_function_breakpoints(functions)
+        self.assertEquals(len(breakpoint_ids), len(functions), 'expect one breakpoint')
+        main_bp_line = line_number('main.cpp', '// main breakpoint 1')
+        breakpoint_ids.append(self.set_source_breakpoints('main.cpp', [main_bp_line]))
+
+        self.continue_to_breakpoints(breakpoint_ids)
+        self.continue_to_exit()
+
+        statistics = self.vscode.wait_for_terminated()['statistics']
+        self.assertTrue(statistics['totalDebugInfoByteSize'] > 0)
+        self.assertTrue(statistics['totalDebugInfoEnabled'] > 0)
+        self.assertTrue(statistics['totalModuleCountHasDebugInfo'] > 0)
+
+        self.assertIsNotNone(statistics['memory'])
+        self.assertNotIn('modules', statistics.keys())
+
+        # lldb-vscode debugs one target at a time
+        target = json.loads(statistics['targets'])[0]
+        self.assertTrue(target['totalBreakpointResolveTime'] > 0)
+
+        breakpoints = target['breakpoints']
+        self.assertIn('foo',
+                      breakpoints[0]['details']['Breakpoint']['BKPTResolver']['Options']['SymbolNames'],
+                      'foo is a symbol breakpoint')
+        self.assertTrue(breakpoints[1]['details']['Breakpoint']['BKPTResolver']['Options']['FileName'].endswith('main.cpp'),
+                        'target has source line breakpoint in main.cpp')
Index: lldb/test/API/tools/lldb-vscode/terminated-event/Makefile
===================================================================
--- /dev/null
+++ lldb/test/API/tools/lldb-vscode/terminated-event/Makefile
@@ -0,0 +1,17 @@
+DYLIB_NAME := foo
+DYLIB_CXX_SOURCES := foo.cpp
+CXX_SOURCES := main.cpp
+
+LD_EXTRAS := -Wl,-rpath "-Wl,$(shell pwd)"
+USE_LIBDL :=1
+
+include Makefile.rules
+
+all: a.out.stripped
+
+a.out.stripped:
+	strip -o a.out.stripped a.out
+
+ifneq "$(CODESIGN)" ""
+	$(CODESIGN) -fs - a.out.stripped
+endif
\ No newline at end of file
Index: lldb/packages/Python/lldbsuite/test/tools/lldb-vscode/vscode.py
===================================================================
--- lldb/packages/Python/lldbsuite/test/tools/lldb-vscode/vscode.py
+++ lldb/packages/Python/lldbsuite/test/tools/lldb-vscode/vscode.py
@@ -369,7 +369,13 @@
     def wait_for_exited(self):
         event_dict = self.wait_for_event('exited')
         if event_dict is None:
-            raise ValueError("didn't get stopped event")
+            raise ValueError("didn't get exited event")
+        return event_dict
+
+    def wait_for_terminated(self):
+        event_dict = self.wait_for_event('terminated')
+        if event_dict is None:
+            raise ValueError("didn't get terminated event")
         return event_dict
 
     def get_initialize_value(self, key):
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to