[Lldb-commits] [lldb] bad6154 - [Reproducers] Serialize process arguments in ProcessInfo

Jonas Devlieghere via lldb-commits lldb-commits at lists.llvm.org
Tue May 12 11:12:44 PDT 2020


Author: Jonas Devlieghere
Date: 2020-05-12T11:12:37-07:00
New Revision: bad61548b2074cf3bf7be2cb4c0d75646e001a73

URL: https://github.com/llvm/llvm-project/commit/bad61548b2074cf3bf7be2cb4c0d75646e001a73
DIFF: https://github.com/llvm/llvm-project/commit/bad61548b2074cf3bf7be2cb4c0d75646e001a73.diff

LOG: [Reproducers] Serialize process arguments in ProcessInfo

While debugging why TestProcessList.py failed during passive replay, I
remembered that we don't serialize the arguments for ProcessInfo. This
is necessary to make the test pass and to make platform process list -v
behave the same during capture and replay.

Differential revision: https://reviews.llvm.org/D79646

Added: 
    lldb/test/Shell/Reproducer/TestProcessList.test

Modified: 
    lldb/include/lldb/Utility/Args.h
    lldb/source/Utility/Args.cpp
    lldb/source/Utility/ProcessInfo.cpp
    lldb/unittests/Utility/ArgsTest.cpp

Removed: 
    


################################################################################
diff  --git a/lldb/include/lldb/Utility/Args.h b/lldb/include/lldb/Utility/Args.h
index 1308f4038dbd..560f25795d3b 100644
--- a/lldb/include/lldb/Utility/Args.h
+++ b/lldb/include/lldb/Utility/Args.h
@@ -14,6 +14,7 @@
 #include "lldb/lldb-types.h"
 #include "llvm/ADT/ArrayRef.h"
 #include "llvm/ADT/StringRef.h"
+#include "llvm/Support/YAMLTraits.h"
 #include <string>
 #include <utility>
 #include <vector>
@@ -34,6 +35,9 @@ class Args {
   struct ArgEntry {
   private:
     friend class Args;
+    friend struct llvm::yaml::MappingTraits<Args>;
+    friend struct llvm::yaml::MappingTraits<Args::ArgEntry>;
+
     std::unique_ptr<char[]> ptr;
     char quote;
 
@@ -283,6 +287,8 @@ class Args {
                                                char quote_char);
 
 private:
+  friend struct llvm::yaml::MappingTraits<Args>;
+
   std::vector<ArgEntry> m_entries;
   std::vector<char *> m_argv;
 };
@@ -373,4 +379,28 @@ class OptionsWithRaw {
 
 } // namespace lldb_private
 
+namespace llvm {
+namespace yaml {
+template <> struct MappingTraits<lldb_private::Args::ArgEntry> {
+  class NormalizedArgEntry {
+  public:
+    NormalizedArgEntry(IO &) {}
+    NormalizedArgEntry(IO &, lldb_private::Args::ArgEntry &entry)
+        : value(entry.ref()), quote(entry.quote) {}
+    lldb_private::Args::ArgEntry denormalize(IO &) {
+      return lldb_private::Args::ArgEntry(value, quote);
+    }
+    StringRef value;
+    char quote;
+  };
+  static void mapping(IO &io, lldb_private::Args::ArgEntry &v);
+};
+template <> struct MappingTraits<lldb_private::Args> {
+  static void mapping(IO &io, lldb_private::Args &v);
+};
+} // namespace yaml
+} // namespace llvm
+
+LLVM_YAML_IS_SEQUENCE_VECTOR(lldb_private::Args::ArgEntry)
+
 #endif // LLDB_UTILITY_ARGS_H

diff  --git a/lldb/source/Utility/Args.cpp b/lldb/source/Utility/Args.cpp
index 443f9bf37cc4..27dcbb822910 100644
--- a/lldb/source/Utility/Args.cpp
+++ b/lldb/source/Utility/Args.cpp
@@ -684,3 +684,20 @@ void OptionsWithRaw::SetFromString(llvm::StringRef arg_string) {
     m_suffix = std::string(original_args);
   }
 }
+
+void llvm::yaml::MappingTraits<Args::ArgEntry>::mapping(IO &io,
+                                                        Args::ArgEntry &v) {
+  MappingNormalization<NormalizedArgEntry, Args::ArgEntry> keys(io, v);
+  io.mapRequired("value", keys->value);
+  io.mapRequired("quote", keys->quote);
+}
+
+void llvm::yaml::MappingTraits<Args>::mapping(IO &io, Args &v) {
+  io.mapRequired("entries", v.m_entries);
+
+  // Recompute m_argv vector.
+  v.m_argv.clear();
+  for (auto &entry : v.m_entries)
+    v.m_argv.push_back(entry.data());
+  v.m_argv.push_back(nullptr);
+}

diff  --git a/lldb/source/Utility/ProcessInfo.cpp b/lldb/source/Utility/ProcessInfo.cpp
index 9a29218f7f1d..aae48d6a4872 100644
--- a/lldb/source/Utility/ProcessInfo.cpp
+++ b/lldb/source/Utility/ProcessInfo.cpp
@@ -337,6 +337,7 @@ void llvm::yaml::MappingTraits<ProcessInstanceInfo>::mapping(
     IO &io, ProcessInstanceInfo &Info) {
   io.mapRequired("executable", Info.m_executable);
   io.mapRequired("arg0", Info.m_arg0);
+  io.mapRequired("args", Info.m_arguments);
   io.mapRequired("arch", Info.m_arch);
   io.mapRequired("uid", Info.m_uid);
   io.mapRequired("gid", Info.m_gid);

diff  --git a/lldb/test/Shell/Reproducer/TestProcessList.test b/lldb/test/Shell/Reproducer/TestProcessList.test
new file mode 100644
index 000000000000..200dcb3febe7
--- /dev/null
+++ b/lldb/test/Shell/Reproducer/TestProcessList.test
@@ -0,0 +1,21 @@
+# UNSUPPORTED: system-freebsd
+
+# Test that ProcessInfo is correctly serialized by comparing the output of
+# 'platform process list -v' during capture and replay. The test assumes that
+# there's at least two processes.
+
+# RUN: %lldb -x -b -o 'platform process list -v' -o 'reproducer generate' --capture --capture-path %t.repro > %t.log
+# RUN: %lldb --replay %t.repro >> %t.log
+# RUN: cat %t.log | FileCheck %s
+
+# CHECK: [[PROCS:[0-9]+]] matching processes were found
+# CHECK: PID    PARENT USER       GROUP      EFF USER   EFF GROUP  TRIPLE                         ARGUMENTS
+# CHECK-NEXT: ====== ====== ========== ========== ========== ========== ============================== ============================
+# CHECK-NEXT: [[PID0:[0-9]+]] [[PROC0:.*]]
+# CHECK-NEXT: [[PID1:[0-9]+]] [[PROC1:.*]]
+# CHECK: Reproducer written to
+# CHECK: [[PROCS]] matching processes were found
+# CHECK: PID    PARENT USER       GROUP      EFF USER   EFF GROUP  TRIPLE                         ARGUMENTS
+# CHECK-NEXT: ====== ====== ========== ========== ========== ========== ============================== ============================
+# CHECK-NEXT: [[PID0]] [[PROC0]]
+# CHECK-NEXT: [[PID1]] [[PROC1]]

diff  --git a/lldb/unittests/Utility/ArgsTest.cpp b/lldb/unittests/Utility/ArgsTest.cpp
index bfbd2ccfdf7b..ed1235f99c71 100644
--- a/lldb/unittests/Utility/ArgsTest.cpp
+++ b/lldb/unittests/Utility/ArgsTest.cpp
@@ -282,3 +282,34 @@ TEST(ArgsTest, ReplaceArgumentAtIndexFarOutOfRange) {
   EXPECT_EQ(3u, args.GetArgumentCount());
   EXPECT_STREQ(args.GetArgumentAtIndex(2), "b");
 }
+
+TEST(ArgsTest, Yaml) {
+  std::string buffer;
+  llvm::raw_string_ostream os(buffer);
+
+  // Serialize.
+  Args args;
+  args.SetCommandString("this 'has' \"multiple\" args");
+  llvm::yaml::Output yout(os);
+  yout << args;
+  os.flush();
+
+  llvm::outs() << buffer;
+
+  // Deserialize.
+  Args deserialized;
+  llvm::yaml::Input yin(buffer);
+  yin >> deserialized;
+
+  EXPECT_EQ(4u, deserialized.GetArgumentCount());
+  EXPECT_STREQ(deserialized.GetArgumentAtIndex(0), "this");
+  EXPECT_STREQ(deserialized.GetArgumentAtIndex(1), "has");
+  EXPECT_STREQ(deserialized.GetArgumentAtIndex(2), "multiple");
+  EXPECT_STREQ(deserialized.GetArgumentAtIndex(3), "args");
+
+  llvm::ArrayRef<Args::ArgEntry> entries = deserialized.entries();
+  EXPECT_EQ(entries[0].GetQuoteChar(), '\0');
+  EXPECT_EQ(entries[1].GetQuoteChar(), '\'');
+  EXPECT_EQ(entries[2].GetQuoteChar(), '"');
+  EXPECT_EQ(entries[3].GetQuoteChar(), '\0');
+}


        


More information about the lldb-commits mailing list