aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2018-02-24 21:28:02 +0000
committerDimitry Andric <dim@FreeBSD.org>2018-02-24 21:28:02 +0000
commitadc606d1b7abc8c35ac3f17bd93691b33b01871e (patch)
tree3efedc36e070498e4ff04a6d36ebe91bca17b470
parent4a80bcabc197f72ab95f7d57c9f32d5807ed3a1d (diff)
downloadsrc-adc606d1b7abc8c35ac3f17bd93691b33b01871e.tar.gz
src-adc606d1b7abc8c35ac3f17bd93691b33b01871e.zip
Vendor import of lldb release_60 branch r325932:vendor/lldb/lldb-release_600-r326565vendor/lldb/lldb-release_60-r325932
Notes
Notes: svn path=/vendor/lldb/dist-release_60/; revision=329939 svn path=/vendor/lldb/lldb-release_600-r326565/; revision=330383; tag=vendor/lldb/lldb-release_600-r326565
-rw-r--r--unittests/tools/lldb-server/tests/MessageObjects.cpp249
-rw-r--r--unittests/tools/lldb-server/tests/MessageObjects.h58
-rw-r--r--unittests/tools/lldb-server/tests/TestClient.cpp85
-rw-r--r--unittests/tools/lldb-server/tests/TestClient.h22
-rw-r--r--unittests/tools/lldb-server/tests/ThreadIdsInJstopinfoTest.cpp14
5 files changed, 290 insertions, 138 deletions
diff --git a/unittests/tools/lldb-server/tests/MessageObjects.cpp b/unittests/tools/lldb-server/tests/MessageObjects.cpp
index e5927d037f98..2ccd6f6123ca 100644
--- a/unittests/tools/lldb-server/tests/MessageObjects.cpp
+++ b/unittests/tools/lldb-server/tests/MessageObjects.cpp
@@ -8,16 +8,17 @@
//===----------------------------------------------------------------------===//
#include "MessageObjects.h"
-#include "lldb/Utility/StructuredData.h"
+#include "lldb/Interpreter/Args.h"
+#include "lldb/Utility/StringExtractor.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)
@@ -53,36 +54,50 @@ Expected<ProcessInfo> ProcessInfo::Create(StringRef response) {
lldb::pid_t ProcessInfo::GetPid() const { return m_pid; }
-endianness ProcessInfo::GetEndian() const { return m_endian; }
+support::endianness ProcessInfo::GetEndian() const { return m_endian; }
//====== ThreadInfo ============================================================
-ThreadInfo::ThreadInfo(StringRef name, StringRef reason,
- const RegisterMap &registers, unsigned int signal)
- : m_name(name.str()), m_reason(reason.str()), m_registers(registers),
- m_signal(signal) {}
-
-StringRef ThreadInfo::ReadRegister(unsigned int register_id) const {
- return m_registers.lookup(register_id);
+ThreadInfo::ThreadInfo(StringRef name, StringRef reason, RegisterMap registers,
+ unsigned int signal)
+ : m_name(name.str()), m_reason(reason.str()),
+ m_registers(std::move(registers)), m_signal(signal) {}
+
+const RegisterValue *ThreadInfo::ReadRegister(unsigned int Id) const {
+ auto Iter = m_registers.find(Id);
+ return Iter == m_registers.end() ? nullptr : &Iter->getSecond();
}
-Expected<uint64_t>
-ThreadInfo::ReadRegisterAsUint64(unsigned int register_id) const {
- uint64_t value;
- std::string value_str(m_registers.lookup(register_id));
- if (!llvm::to_integer(value_str, value, 16))
- return make_parsing_error("ThreadInfo value for register {0}: {1}",
- register_id, value_str);
+//====== JThreadsInfo ==========================================================
- sys::swapByteOrder(value);
- return value;
+Expected<RegisterMap>
+JThreadsInfo::parseRegisters(const StructuredData::Dictionary &Dict,
+ ArrayRef<RegisterInfo> RegInfos) {
+ RegisterMap Result;
+
+ auto KeysObj = Dict.GetKeys();
+ auto Keys = KeysObj->GetAsArray();
+ for (size_t i = 0; i < Keys->GetSize(); i++) {
+ StringRef KeyStr, ValueStr;
+ Keys->GetItemAtIndexAsString(i, KeyStr);
+ Dict.GetValueForKeyAsString(KeyStr, ValueStr);
+ unsigned int Register;
+ if (!llvm::to_integer(KeyStr, Register, 10))
+ return make_parsing_error("JThreadsInfo: register key[{0}]", i);
+
+ auto RegValOr =
+ parseRegisterValue(RegInfos[Register], ValueStr, support::big);
+ if (!RegValOr)
+ return RegValOr.takeError();
+ Result[Register] = std::move(*RegValOr);
+ }
+ return std::move(Result);
}
-//====== JThreadsInfo ==========================================================
-Expected<JThreadsInfo> JThreadsInfo::Create(StringRef response,
- endianness endian) {
+Expected<JThreadsInfo> JThreadsInfo::create(StringRef Response,
+ ArrayRef<RegisterInfo> RegInfos) {
JThreadsInfo jthreads_info;
- StructuredData::ObjectSP json = StructuredData::ParseJSON(response);
+ StructuredData::ObjectSP json = StructuredData::ParseJSON(Response);
StructuredData::Array *array = json->GetAsArray();
if (!array)
return make_parsing_error("JThreadsInfo: JSON array");
@@ -106,23 +121,11 @@ Expected<JThreadsInfo> JThreadsInfo::Create(StringRef response,
if (!register_dict)
return make_parsing_error("JThreadsInfo: registers JSON obj");
- RegisterMap registers;
-
- auto keys_obj = register_dict->GetKeys();
- auto keys = keys_obj->GetAsArray();
- for (size_t i = 0; i < keys->GetSize(); i++) {
- StringRef key_str, value_str;
- keys->GetItemAtIndexAsString(i, key_str);
- register_dict->GetValueForKeyAsString(key_str, value_str);
- unsigned int register_id;
- if (key_str.getAsInteger(10, register_id))
- return make_parsing_error("JThreadsInfo: register key[{0}]", i);
-
- registers[register_id] = value_str.str();
- }
-
+ auto RegsOr = parseRegisters(*register_dict, RegInfos);
+ if (!RegsOr)
+ return RegsOr.takeError();
jthreads_info.m_thread_infos[tid] =
- ThreadInfo(name, reason, registers, signal);
+ ThreadInfo(name, reason, std::move(*RegsOr), signal);
}
return jthreads_info;
@@ -132,20 +135,130 @@ const ThreadInfoMap &JThreadsInfo::GetThreadInfos() const {
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);
+}
+
+Expected<RegisterValue> parseRegisterValue(const RegisterInfo &Info,
+ StringRef HexValue,
+ llvm::support::endianness Endian) {
+ SmallVector<uint8_t, 64> Bytes(HexValue.size() / 2);
+ StringExtractor(HexValue).GetHexBytes(Bytes, '\xcc');
+ RegisterValue Value;
+ Status ST;
+ Value.SetFromMemoryData(
+ &Info, Bytes.data(), Bytes.size(),
+ Endian == support::little ? eByteOrderLittle : eByteOrderBig, ST);
+ if (ST.Fail())
+ return ST.ToError();
+ return Value;
+}
+
//====== StopReply =============================================================
Expected<std::unique_ptr<StopReply>>
-StopReply::create(StringRef Response, llvm::support::endianness Endian) {
+StopReply::create(StringRef Response, llvm::support::endianness Endian,
+ ArrayRef<RegisterInfo> RegInfos) {
if (Response.size() < 3)
return make_parsing_error("StopReply: Invalid packet");
if (Response.consume_front("T"))
- return StopReplyStop::create(Response, Endian);
+ return StopReplyStop::create(Response, Endian, RegInfos);
if (Response.consume_front("W"))
return StopReplyExit::create(Response);
return make_parsing_error("StopReply: Invalid packet");
}
+Expected<RegisterMap> StopReplyStop::parseRegisters(
+ const StringMap<SmallVector<StringRef, 2>> &Elements,
+ support::endianness Endian, ArrayRef<lldb_private::RegisterInfo> RegInfos) {
+
+ RegisterMap Result;
+ for (const auto &E : Elements) {
+ StringRef Key = E.getKey();
+ const auto &Val = E.getValue();
+ if (Key.size() != 2)
+ continue;
+
+ unsigned int Reg;
+ if (!to_integer(Key, Reg, 16))
+ continue;
+
+ if (Val.size() != 1)
+ return make_parsing_error(
+ "StopReplyStop: multiple entries for register field [{0:x}]", Reg);
+
+ auto RegValOr = parseRegisterValue(RegInfos[Reg], Val[0], Endian);
+ if (!RegValOr)
+ return RegValOr.takeError();
+ Result[Reg] = std::move(*RegValOr);
+ }
+ return std::move(Result);
+}
+
Expected<std::unique_ptr<StopReplyStop>>
-StopReplyStop::create(StringRef Response, llvm::support::endianness Endian) {
+StopReplyStop::create(StringRef Response, support::endianness Endian,
+ ArrayRef<RegisterInfo> RegInfos) {
unsigned int Signal;
StringRef SignalStr = Response.take_front(2);
Response = Response.drop_front(2);
@@ -176,40 +289,31 @@ StopReplyStop::create(StringRef Response, llvm::support::endianness Endian) {
if (Threads.size() != Pcs.size())
return make_parsing_error("StopReply: thread/PC count mismatch");
- U64Map ThreadPcs;
+ RegisterMap ThreadPcs;
+ const RegisterInfo *PcInfo = find_if(RegInfos, [](const RegisterInfo &Info) {
+ return Info.kinds[eRegisterKindGeneric] == LLDB_REGNUM_GENERIC_PC;
+ });
+ assert(PcInfo);
+
for (auto ThreadPc : zip(Threads, Pcs)) {
lldb::tid_t Id;
- uint64_t Pc;
if (!to_integer(std::get<0>(ThreadPc), Id, 16))
return make_parsing_error("StopReply: Thread id '{0}'",
std::get<0>(ThreadPc));
- if (!to_integer(std::get<1>(ThreadPc), Pc, 16))
- return make_parsing_error("StopReply Thread Pc '{0}'",
- std::get<1>(ThreadPc));
- ThreadPcs[Id] = Pc;
+ auto PcOr = parseRegisterValue(*PcInfo, std::get<1>(ThreadPc), Endian);
+ if (!PcOr)
+ return PcOr.takeError();
+ ThreadPcs[Id] = std::move(*PcOr);
}
- RegisterMap Registers;
- for (const auto &E : Elements) {
- StringRef Key = E.getKey();
- const auto &Val = E.getValue();
- if (Key.size() != 2)
- continue;
-
- unsigned int Reg;
- if (!to_integer(Key, Reg, 16))
- continue;
+ auto RegistersOr = parseRegisters(Elements, Endian, RegInfos);
+ if (!RegistersOr)
+ return RegistersOr.takeError();
- if (Val.size() != 1)
- return make_parsing_error(
- "StopReply: multiple entries for register field [{0:x}]", Reg);
-
- Registers[Reg] = Val[0].str();
- }
-
- return llvm::make_unique<StopReplyStop>(Signal, Thread, Name, ThreadPcs,
- Registers, Reason);
+ return llvm::make_unique<StopReplyStop>(Signal, Thread, Name,
+ std::move(ThreadPcs),
+ std::move(*RegistersOr), Reason);
}
Expected<std::unique_ptr<StopReplyExit>>
@@ -251,3 +355,12 @@ StringMap<SmallVector<StringRef, 2>> SplitPairList(StringRef str) {
return pairs;
}
} // namespace llgs_tests
+
+std::ostream &lldb_private::operator<<(std::ostream &OS,
+ const RegisterValue &RegVal) {
+ ArrayRef<uint8_t> Bytes(static_cast<const uint8_t *>(RegVal.GetBytes()),
+ RegVal.GetByteSize());
+ return OS << formatv("RegisterValue[{0}]: {1:@[x-2]}", RegVal.GetByteSize(),
+ make_range(Bytes.begin(), Bytes.end()))
+ .str();
+}
diff --git a/unittests/tools/lldb-server/tests/MessageObjects.h b/unittests/tools/lldb-server/tests/MessageObjects.h
index bbb7f75bafd5..4f540ec20e7a 100644
--- a/unittests/tools/lldb-server/tests/MessageObjects.h
+++ b/unittests/tools/lldb-server/tests/MessageObjects.h
@@ -10,7 +10,9 @@
#ifndef LLDB_SERVER_TESTS_MESSAGEOBJECTS_H
#define LLDB_SERVER_TESTS_MESSAGEOBJECTS_H
+#include "lldb/Core/RegisterValue.h"
#include "lldb/Host/Host.h"
+#include "lldb/Utility/StructuredData.h"
#include "lldb/lldb-types.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallString.h"
@@ -22,12 +24,13 @@
namespace llgs_tests {
class ThreadInfo;
typedef llvm::DenseMap<uint64_t, ThreadInfo> ThreadInfoMap;
-typedef llvm::DenseMap<uint64_t, uint64_t> U64Map;
-typedef llvm::DenseMap<unsigned int, std::string> RegisterMap;
+typedef llvm::DenseMap<unsigned int, lldb_private::RegisterValue> 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;
@@ -49,10 +52,9 @@ class ThreadInfo {
public:
ThreadInfo() = default;
ThreadInfo(llvm::StringRef name, llvm::StringRef reason,
- const RegisterMap &registers, unsigned int signal);
+ RegisterMap registers, unsigned int signal);
- llvm::StringRef ReadRegister(unsigned int register_id) const;
- llvm::Expected<uint64_t> ReadRegisterAsUint64(unsigned int register_id) const;
+ const lldb_private::RegisterValue *ReadRegister(unsigned int Id) const;
private:
std::string m_name;
@@ -61,25 +63,40 @@ private:
unsigned int m_signal;
};
-class JThreadsInfo {
+class JThreadsInfo : public Parser<JThreadsInfo> {
public:
- static llvm::Expected<JThreadsInfo> Create(llvm::StringRef response,
- llvm::support::endianness endian);
+ static llvm::Expected<JThreadsInfo>
+ create(llvm::StringRef Response,
+ llvm::ArrayRef<lldb_private::RegisterInfo> RegInfos);
const ThreadInfoMap &GetThreadInfos() const;
private:
+ static llvm::Expected<RegisterMap>
+ parseRegisters(const lldb_private::StructuredData::Dictionary &Dict,
+ llvm::ArrayRef<lldb_private::RegisterInfo> RegInfos);
+
JThreadsInfo() = default;
ThreadInfoMap m_thread_infos;
};
+struct RegisterInfoParser : public Parser<lldb_private::RegisterInfo> {
+ static llvm::Expected<lldb_private::RegisterInfo>
+ create(llvm::StringRef Response);
+};
+
+llvm::Expected<lldb_private::RegisterValue>
+parseRegisterValue(const lldb_private::RegisterInfo &Info,
+ llvm::StringRef HexValue, llvm::support::endianness Endian);
+
class StopReply {
public:
StopReply() = default;
virtual ~StopReply() = default;
static llvm::Expected<std::unique_ptr<StopReply>>
- create(llvm::StringRef response, llvm::support::endianness endian);
+ create(llvm::StringRef Response, llvm::support::endianness Endian,
+ llvm::ArrayRef<lldb_private::RegisterInfo> RegInfos);
// for llvm::cast<>
virtual lldb_private::WaitStatus getKind() const = 0;
@@ -91,15 +108,17 @@ public:
class StopReplyStop : public StopReply {
public:
StopReplyStop(uint8_t Signal, lldb::tid_t ThreadId, llvm::StringRef Name,
- U64Map ThreadPcs, RegisterMap Registers, llvm::StringRef Reason)
+ RegisterMap ThreadPcs, RegisterMap Registers,
+ llvm::StringRef Reason)
: Signal(Signal), ThreadId(ThreadId), Name(Name),
ThreadPcs(std::move(ThreadPcs)), Registers(std::move(Registers)),
Reason(Reason) {}
static llvm::Expected<std::unique_ptr<StopReplyStop>>
- create(llvm::StringRef response, llvm::support::endianness endian);
+ create(llvm::StringRef Response, llvm::support::endianness Endian,
+ llvm::ArrayRef<lldb_private::RegisterInfo> RegInfos);
- const U64Map &getThreadPcs() const { return ThreadPcs; }
+ const RegisterMap &getThreadPcs() const { return ThreadPcs; }
lldb::tid_t getThreadId() const { return ThreadId; }
// for llvm::cast<>
@@ -111,10 +130,15 @@ public:
}
private:
+ static llvm::Expected<RegisterMap> parseRegisters(
+ const llvm::StringMap<llvm::SmallVector<llvm::StringRef, 2>> &Elements,
+ llvm::support::endianness Endian,
+ llvm::ArrayRef<lldb_private::RegisterInfo> RegInfos);
+
uint8_t Signal;
lldb::tid_t ThreadId;
std::string Name;
- U64Map ThreadPcs;
+ RegisterMap ThreadPcs;
RegisterMap Registers;
std::string Reason;
};
@@ -156,4 +180,8 @@ llvm::Error make_parsing_error(llvm::StringRef format, Args &&... args) {
} // namespace llgs_tests
+namespace lldb_private {
+std::ostream &operator<<(std::ostream &OS, const RegisterValue &RegVal);
+}
+
#endif // LLDB_SERVER_TESTS_MESSAGEOBJECTS_H
diff --git a/unittests/tools/lldb-server/tests/TestClient.cpp b/unittests/tools/lldb-server/tests/TestClient.cpp
index 4653c2df1ce9..9396c23139a1 100644
--- a/unittests/tools/lldb-server/tests/TestClient.cpp
+++ b/unittests/tools/lldb-server/tests/TestClient.cpp
@@ -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());
@@ -106,7 +105,7 @@ Expected<std::unique_ptr<TestClient>> TestClient::launchCustom(StringRef Log, Ar
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);
}
@@ -136,7 +135,7 @@ Error TestClient::SetInferior(llvm::ArrayRef<std::string> inferior_args) {
return E;
if (Error E = SendMessage("qLaunchSuccess"))
return E;
- if (Error E = QueryProcessInfo())
+ if (Error E = queryProcess())
return E;
return Error::success();
}
@@ -155,19 +154,12 @@ Error TestClient::ContinueThread(unsigned long thread_id) {
return Continue(formatv("vCont;c:{0:x-}", thread_id).str());
}
-const ProcessInfo &TestClient::GetProcessInfo() { return *m_process_info; }
-
-Optional<JThreadsInfo> TestClient::GetJThreadsInfo() {
- std::string response;
- if (SendMessage("jThreadsInfo", response))
- return llvm::None;
- auto creation = JThreadsInfo::Create(response, m_process_info->GetEndian());
- if (auto create_error = creation.takeError()) {
- GTEST_LOG_(ERROR) << toString(std::move(create_error));
- return llvm::None;
- }
+const llgs_tests::ProcessInfo &TestClient::GetProcessInfo() {
+ return *m_process_info;
+}
- return std::move(*creation);
+Expected<JThreadsInfo> TestClient::GetJThreadsInfo() {
+ return SendMessage<JThreadsInfo>("jThreadsInfo", m_register_infos);
}
const StopReply &TestClient::GetLatestStopReply() {
@@ -209,42 +201,42 @@ Error TestClient::SendMessage(StringRef message, std::string &response_string,
}
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();
}
@@ -254,7 +246,8 @@ Error TestClient::Continue(StringRef message) {
std::string response;
if (Error E = SendMessage(message, response))
return E;
- auto creation = StopReply::create(response, m_process_info->GetEndian());
+ auto creation = StopReply::create(response, m_process_info->GetEndian(),
+ m_register_infos);
if (Error E = creation.takeError())
return E;
@@ -273,5 +266,3 @@ Error TestClient::Continue(StringRef message) {
}
return Error::success();
}
-
-} // namespace llgs_tests
diff --git a/unittests/tools/lldb-server/tests/TestClient.h b/unittests/tools/lldb-server/tests/TestClient.h
index b5195307876d..ebcb4a549b39 100644
--- a/unittests/tools/lldb-server/tests/TestClient.h
+++ b/unittests/tools/lldb-server/tests/TestClient.h
@@ -59,7 +59,7 @@ public:
llvm::Error ContinueAll();
llvm::Error ContinueThread(unsigned long thread_id);
const ProcessInfo &GetProcessInfo();
- llvm::Optional<JThreadsInfo> GetJThreadsInfo();
+ llvm::Expected<JThreadsInfo> GetJThreadsInfo();
const StopReply &GetLatestStopReply();
template <typename T> llvm::Expected<const T &> GetLatestStopReplyAs() {
assert(m_stop_reply);
@@ -74,12 +74,18 @@ public:
std::string &response_string);
llvm::Error SendMessage(llvm::StringRef message, std::string &response_string,
PacketResult expected_result);
+
+ template <typename P, typename... CreateArgs>
+ llvm::Expected<typename P::result_type> SendMessage(llvm::StringRef Message,
+ CreateArgs &&... Args);
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 +94,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, typename... CreateArgs>
+llvm::Expected<typename P::result_type>
+TestClient::SendMessage(llvm::StringRef Message, CreateArgs &&... Args) {
+ std::string ResponseText;
+ if (llvm::Error E = SendMessage(Message, ResponseText))
+ return std::move(E);
+ return P::create(ResponseText, std::forward<CreateArgs>(Args)...);
+}
+
} // namespace llgs_tests
#endif // LLDB_SERVER_TESTS_TESTCLIENT_H
diff --git a/unittests/tools/lldb-server/tests/ThreadIdsInJstopinfoTest.cpp b/unittests/tools/lldb-server/tests/ThreadIdsInJstopinfoTest.cpp
index 6ff777bd17ab..efc9517bc4b4 100644
--- a/unittests/tools/lldb-server/tests/ThreadIdsInJstopinfoTest.cpp
+++ b/unittests/tools/lldb-server/tests/ThreadIdsInJstopinfoTest.cpp
@@ -9,13 +9,19 @@
#include "TestBase.h"
#include "TestClient.h"
+#include "lldb/Utility/DataExtractor.h"
+#include "llvm/Support/FormatVariadic.h"
#include "llvm/Support/Path.h"
#include "llvm/Testing/Support/Error.h"
+#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include <string>
using namespace llgs_tests;
+using namespace lldb_private;
using namespace llvm;
+using namespace lldb;
+using namespace testing;
TEST_F(StandardStartupTest, TestStopReplyContainsThreadPcs) {
// This inferior spawns 4 threads, then forces a break.
@@ -29,7 +35,7 @@ TEST_F(StandardStartupTest, TestStopReplyContainsThreadPcs) {
ASSERT_NE(pc_reg, UINT_MAX);
auto jthreads_info = Client->GetJThreadsInfo();
- ASSERT_TRUE(jthreads_info);
+ ASSERT_THAT_EXPECTED(jthreads_info, Succeeded());
auto stop_reply = Client->GetLatestStopReplyAs<StopReplyStop>();
ASSERT_THAT_EXPECTED(stop_reply, Succeeded());
@@ -42,9 +48,7 @@ TEST_F(StandardStartupTest, TestStopReplyContainsThreadPcs) {
unsigned long tid = stop_reply_pc.first;
ASSERT_TRUE(thread_infos.find(tid) != thread_infos.end())
<< "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)
- << "Mismatched PC for thread: " << tid;
+ EXPECT_THAT(thread_infos[tid].ReadRegister(pc_reg),
+ Pointee(Eq(stop_reply_pc.second)));
}
}