[Lldb-commits] [lldb] r324722 - llgs-test: Parse and store register info recieved from lldb-server

Pavel Labath via lldb-commits lldb-commits at lists.llvm.org
Fri Feb 9 01:40:03 PST 2018


Author: labath
Date: Fri Feb  9 01:40:03 2018
New Revision: 324722

URL: http://llvm.org/viewvc/llvm-project?rev=324722&view=rev
Log:
llgs-test: Parse and store register info recieved from lldb-server

Summary:
Right now the test client is not parsing register values correctly,
which is manifesting itself in one test failing on 32-bit architectures
(pr36013). This parses the information from the qRegisterInfo packets
and stores it in the client, which will enable fixing the parsing in a
follow up commit.

I am also adding a new templated SendMessage overload, which enables one
to send a message get a parsed response in a single call.

Reviewers: eugene, davide

Subscribers: lldb-commits

Differential Revision: https://reviews.llvm.org/D43076

Modified:
    lldb/trunk/unittests/tools/lldb-server/tests/MessageObjects.cpp
    lldb/trunk/unittests/tools/lldb-server/tests/MessageObjects.h
    lldb/trunk/unittests/tools/lldb-server/tests/TestClient.cpp
    lldb/trunk/unittests/tools/lldb-server/tests/TestClient.h
    lldb/trunk/unittests/tools/lldb-server/tests/ThreadIdsInJstopinfoTest.cpp

Modified: lldb/trunk/unittests/tools/lldb-server/tests/MessageObjects.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/unittests/tools/lldb-server/tests/MessageObjects.cpp?rev=324722&r1=324721&r2=324722&view=diff
==============================================================================
--- lldb/trunk/unittests/tools/lldb-server/tests/MessageObjects.cpp (original)
+++ lldb/trunk/unittests/tools/lldb-server/tests/MessageObjects.cpp Fri Feb  9 01:40:03 2018
@@ -8,16 +8,18 @@
 //===----------------------------------------------------------------------===//
 
 #include "MessageObjects.h"
+#include "lldb/Interpreter/Args.h"
 #include "lldb/Utility/StructuredData.h"
 #include "llvm/ADT/StringExtras.h"
 #include "gtest/gtest.h"
 
 using namespace lldb_private;
+using namespace lldb;
 using namespace llvm;
 using namespace llvm::support;
 namespace llgs_tests {
 
-Expected<ProcessInfo> ProcessInfo::Create(StringRef response) {
+Expected<ProcessInfo> ProcessInfo::create(StringRef response) {
   ProcessInfo process_info;
   auto elements_or_error = SplitUniquePairList("ProcessInfo", response);
   if (!elements_or_error)
@@ -132,6 +134,72 @@ const ThreadInfoMap &JThreadsInfo::GetTh
   return m_thread_infos;
 }
 
+Expected<RegisterInfo> RegisterInfoParser::create(StringRef Response) {
+  auto ElementsOr = SplitUniquePairList("RegisterInfoParser", Response);
+  if (!ElementsOr)
+    return ElementsOr.takeError();
+  auto &Elements = *ElementsOr;
+
+  RegisterInfo Info = {
+      nullptr,       // Name
+      nullptr,       // Alt name
+      0,             // byte size
+      0,             // offset
+      eEncodingUint, // encoding
+      eFormatHex,    // format
+      {
+          LLDB_INVALID_REGNUM, // eh_frame reg num
+          LLDB_INVALID_REGNUM, // DWARF reg num
+          LLDB_INVALID_REGNUM, // generic reg num
+          LLDB_INVALID_REGNUM, // process plugin reg num
+          LLDB_INVALID_REGNUM  // native register number
+      },
+      NULL,
+      NULL,
+      NULL, // Dwarf expression opcode bytes pointer
+      0     // Dwarf expression opcode bytes length
+  };
+  Info.name = ConstString(Elements["name"]).GetCString();
+  if (!Info.name)
+    return make_parsing_error("qRegisterInfo: name");
+
+  Info.alt_name = ConstString(Elements["alt-name"]).GetCString();
+
+  if (!to_integer(Elements["bitsize"], Info.byte_size, 10))
+    return make_parsing_error("qRegisterInfo: bit-size");
+  Info.byte_size /= CHAR_BIT;
+
+  if (!to_integer(Elements["offset"], Info.byte_offset, 10))
+    return make_parsing_error("qRegisterInfo: offset");
+
+  Info.encoding = Args::StringToEncoding(Elements["encoding"]);
+  if (Info.encoding == eEncodingInvalid)
+    return make_parsing_error("qRegisterInfo: encoding");
+
+  Info.format = StringSwitch<Format>(Elements["format"])
+                    .Case("binary", eFormatBinary)
+                    .Case("decimal", eFormatDecimal)
+                    .Case("hex", eFormatHex)
+                    .Case("float", eFormatFloat)
+                    .Case("vector-sint8", eFormatVectorOfSInt8)
+                    .Case("vector-uint8", eFormatVectorOfUInt8)
+                    .Case("vector-sint16", eFormatVectorOfSInt16)
+                    .Case("vector-uint16", eFormatVectorOfUInt16)
+                    .Case("vector-sint32", eFormatVectorOfSInt32)
+                    .Case("vector-uint32", eFormatVectorOfUInt32)
+                    .Case("vector-float32", eFormatVectorOfFloat32)
+                    .Case("vector-uint64", eFormatVectorOfUInt64)
+                    .Case("vector-uint128", eFormatVectorOfUInt128)
+                    .Default(eFormatInvalid);
+  if (Info.format == eFormatInvalid)
+    return make_parsing_error("qRegisterInfo: format");
+
+  Info.kinds[eRegisterKindGeneric] =
+      Args::StringToGenericRegister(Elements["generic"]);
+
+  return std::move(Info);
+}
+
 //====== StopReply =============================================================
 Expected<std::unique_ptr<StopReply>>
 StopReply::create(StringRef Response, llvm::support::endianness Endian) {

Modified: lldb/trunk/unittests/tools/lldb-server/tests/MessageObjects.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/unittests/tools/lldb-server/tests/MessageObjects.h?rev=324722&r1=324721&r2=324722&view=diff
==============================================================================
--- lldb/trunk/unittests/tools/lldb-server/tests/MessageObjects.h (original)
+++ lldb/trunk/unittests/tools/lldb-server/tests/MessageObjects.h Fri Feb  9 01:40:03 2018
@@ -25,9 +25,11 @@ typedef llvm::DenseMap<uint64_t, ThreadI
 typedef llvm::DenseMap<uint64_t, uint64_t> U64Map;
 typedef llvm::DenseMap<unsigned int, std::string> RegisterMap;
 
-class ProcessInfo {
+template <typename T> struct Parser { using result_type = T; };
+
+class ProcessInfo : public Parser<ProcessInfo> {
 public:
-  static llvm::Expected<ProcessInfo> Create(llvm::StringRef response);
+  static llvm::Expected<ProcessInfo> create(llvm::StringRef response);
   lldb::pid_t GetPid() const;
   llvm::support::endianness GetEndian() const;
 
@@ -73,6 +75,11 @@ private:
   ThreadInfoMap m_thread_infos;
 };
 
+struct RegisterInfoParser : public Parser<lldb_private::RegisterInfo> {
+  static llvm::Expected<lldb_private::RegisterInfo>
+  create(llvm::StringRef Response);
+};
+
 class StopReply {
 public:
   StopReply() = default;

Modified: lldb/trunk/unittests/tools/lldb-server/tests/TestClient.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/unittests/tools/lldb-server/tests/TestClient.cpp?rev=324722&r1=324721&r2=324722&view=diff
==============================================================================
--- lldb/trunk/unittests/tools/lldb-server/tests/TestClient.cpp (original)
+++ lldb/trunk/unittests/tools/lldb-server/tests/TestClient.cpp Fri Feb  9 01:40:03 2018
@@ -25,8 +25,7 @@
 using namespace lldb;
 using namespace lldb_private;
 using namespace llvm;
-
-namespace llgs_tests {
+using namespace llgs_tests;
 
 TestClient::TestClient(std::unique_ptr<Connection> Conn) {
   SetConnection(Conn.release());
@@ -103,7 +102,7 @@ Expected<std::unique_ptr<TestClient>> Te
   auto Client = std::unique_ptr<TestClient>(new TestClient(std::move(Conn)));
 
   if (!InferiorArgs.empty()) {
-    if (Error E = Client->QueryProcessInfo())
+    if (Error E = Client->queryProcess())
       return std::move(E);
   }
 
@@ -128,7 +127,7 @@ Error TestClient::SetInferior(llvm::Arra
     return E;
   if (Error E = SendMessage("qLaunchSuccess"))
     return E;
-  if (Error E = QueryProcessInfo())
+  if (Error E = queryProcess())
     return E;
   return Error::success();
 }
@@ -147,7 +146,9 @@ Error TestClient::ContinueThread(unsigne
   return Continue(formatv("vCont;c:{0:x-}", thread_id).str());
 }
 
-const ProcessInfo &TestClient::GetProcessInfo() { return *m_process_info; }
+const llgs_tests::ProcessInfo &TestClient::GetProcessInfo() {
+  return *m_process_info;
+}
 
 Optional<JThreadsInfo> TestClient::GetJThreadsInfo() {
   std::string response;
@@ -201,42 +202,42 @@ Error TestClient::SendMessage(StringRef
 }
 
 unsigned int TestClient::GetPcRegisterId() {
-  if (m_pc_register != UINT_MAX)
-    return m_pc_register;
-
-  for (unsigned int register_id = 0;; register_id++) {
-    std::string message = formatv("qRegisterInfo{0:x-}", register_id).str();
-    std::string response;
-    if (SendMessage(message, response)) {
-      GTEST_LOG_(ERROR) << "Unable to query register ID for PC register.";
-      return UINT_MAX;
-    }
+  assert(m_pc_register != LLDB_INVALID_REGNUM);
+  return m_pc_register;
+}
 
-    auto elements_or_error = SplitUniquePairList("GetPcRegisterId", response);
-    if (auto split_error = elements_or_error.takeError()) {
-      GTEST_LOG_(ERROR) << "GetPcRegisterId: Error splitting response: "
-                        << response;
-      return UINT_MAX;
-    }
+Error TestClient::qProcessInfo() {
+  m_process_info = None;
+  auto InfoOr = SendMessage<ProcessInfo>("qProcessInfo");
+  if (!InfoOr)
+    return InfoOr.takeError();
+  m_process_info = std::move(*InfoOr);
+  return Error::success();
+}
 
-    auto elements = *elements_or_error;
-    if (elements["alt-name"] == "pc" || elements["generic"] == "pc") {
-      m_pc_register = register_id;
+Error TestClient::qRegisterInfos() {
+  for (unsigned int Reg = 0;; ++Reg) {
+    std::string Message = formatv("qRegisterInfo{0:x-}", Reg).str();
+    Expected<RegisterInfo> InfoOr = SendMessage<RegisterInfoParser>(Message);
+    if (!InfoOr) {
+      consumeError(InfoOr.takeError());
       break;
     }
+    m_register_infos.emplace_back(std::move(*InfoOr));
+    if (m_register_infos[Reg].kinds[eRegisterKindGeneric] ==
+        LLDB_REGNUM_GENERIC_PC)
+      m_pc_register = Reg;
   }
-
-  return m_pc_register;
+  if (m_pc_register == LLDB_INVALID_REGNUM)
+    return make_parsing_error("qRegisterInfo: generic");
+  return Error::success();
 }
 
-llvm::Error TestClient::QueryProcessInfo() {
-  std::string response;
-  if (Error E = SendMessage("qProcessInfo", response))
+Error TestClient::queryProcess() {
+  if (Error E = qProcessInfo())
+    return E;
+  if (Error E = qRegisterInfos())
     return E;
-  auto create_or_error = ProcessInfo::Create(response);
-  if (!create_or_error)
-    return create_or_error.takeError();
-  m_process_info = *create_or_error;
   return Error::success();
 }
 
@@ -265,5 +266,3 @@ Error TestClient::Continue(StringRef mes
   }
   return Error::success();
 }
-
-} // namespace llgs_tests

Modified: lldb/trunk/unittests/tools/lldb-server/tests/TestClient.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/unittests/tools/lldb-server/tests/TestClient.h?rev=324722&r1=324721&r2=324722&view=diff
==============================================================================
--- lldb/trunk/unittests/tools/lldb-server/tests/TestClient.h (original)
+++ lldb/trunk/unittests/tools/lldb-server/tests/TestClient.h Fri Feb  9 01:40:03 2018
@@ -74,12 +74,17 @@ public:
                           std::string &response_string);
   llvm::Error SendMessage(llvm::StringRef message, std::string &response_string,
                           PacketResult expected_result);
+
+  template <typename P>
+  llvm::Expected<typename P::result_type> SendMessage(llvm::StringRef Message);
   unsigned int GetPcRegisterId();
 
 private:
   TestClient(std::unique_ptr<lldb_private::Connection> Conn);
 
-  llvm::Error QueryProcessInfo();
+  llvm::Error qProcessInfo();
+  llvm::Error qRegisterInfos();
+  llvm::Error queryProcess();
   llvm::Error Continue(llvm::StringRef message);
   std::string FormatFailedResult(
       const std::string &message,
@@ -88,9 +93,19 @@ private:
 
   llvm::Optional<ProcessInfo> m_process_info;
   std::unique_ptr<StopReply> m_stop_reply;
-  unsigned int m_pc_register = UINT_MAX;
+  std::vector<lldb_private::RegisterInfo> m_register_infos;
+  unsigned int m_pc_register = LLDB_INVALID_REGNUM;
 };
 
+template <typename P>
+llvm::Expected<typename P::result_type>
+TestClient::SendMessage(llvm::StringRef Message) {
+  std::string ResponseText;
+  if (llvm::Error E = SendMessage(Message, ResponseText))
+    return std::move(E);
+  return P::create(ResponseText);
+}
+
 } // namespace llgs_tests
 
 #endif // LLDB_SERVER_TESTS_TESTCLIENT_H

Modified: lldb/trunk/unittests/tools/lldb-server/tests/ThreadIdsInJstopinfoTest.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/unittests/tools/lldb-server/tests/ThreadIdsInJstopinfoTest.cpp?rev=324722&r1=324721&r2=324722&view=diff
==============================================================================
--- lldb/trunk/unittests/tools/lldb-server/tests/ThreadIdsInJstopinfoTest.cpp (original)
+++ lldb/trunk/unittests/tools/lldb-server/tests/ThreadIdsInJstopinfoTest.cpp Fri Feb  9 01:40:03 2018
@@ -44,7 +44,7 @@ TEST_F(StandardStartupTest, TestStopRepl
         << "Thread ID: " << tid << " not in JThreadsInfo.";
     auto pc_value = thread_infos[tid].ReadRegisterAsUint64(pc_reg);
     ASSERT_THAT_EXPECTED(pc_value, Succeeded());
-    ASSERT_EQ(stop_reply_pcs[tid], *pc_value)
+    ASSERT_EQ(stop_reply_pc.second, *pc_value)
         << "Mismatched PC for thread: " << tid;
   }
 }




More information about the lldb-commits mailing list