Index: experimental/windows_debugger/debugger/rsp/rsp_packet.cc |
diff --git a/experimental/windows_debugger/debugger/rsp/rsp_packet.cc b/experimental/windows_debugger/debugger/rsp/rsp_packet.cc |
deleted file mode 100644 |
index 4b2c398f2156cab75cb9ab3916ada35856851b00..0000000000000000000000000000000000000000 |
--- a/experimental/windows_debugger/debugger/rsp/rsp_packet.cc |
+++ /dev/null |
@@ -1,532 +0,0 @@ |
-// Copyright (c) 2011 The Native Client Authors. All rights reserved. |
-// Use of this source code is governed by a BSD-style license that can be |
-// found in the LICENSE file. |
-#include "debugger/rsp/rsp_packet.h" |
- |
-#pragma warning(disable : 4996) // Disable _snprintf warning. |
- |
-namespace { |
-bool HexStringToInt(const std::string& str, int* number); |
-void RemoveSpacesFromBothEnds(std::deque<debug::Blob>* tokens); |
- |
-void InitFactory(); |
-std::map<std::string, rsp::Packet*> packet_factory_; |
-} // namespace |
- |
-namespace rsp { |
-/// Note: this method modifies |message|. |
-/// Note: returned obj shall be deleted. |
-/// |
-/// Why |type_hint|? Because some RSP packets don't carry type field. |
-/// Examples: |
-/// 1. replies to 'm' (read memory) command: |
-/// H>[mc000202e0,12] |
-/// T>[554889e583ec204c01fc897dec8975e8c745] |
-/// => supply "blob$Reply" as a |type_hint| |
-/// |
-/// 2. replies to 'g' (read registers) command: |
-/// H>[g] |
-/// T>[00000000000000000000000000000000d85123... |
-/// => supply "blob$Reply" as a |type_hint| |
-/// |
-/// 3. replies to 'qSupported' command: |
-/// H>[qSupported:xmlRegisters=i386;qRelocInsn+] |
-/// T>[PacketSize=7cf;qXfer:libraries:read+;qXfer:features:read+] |
-/// => supply "qSupported$Reply" as a |type_hint| |
-/// |
-/// 4. replies to 'qXfer' command: |
-/// supply "qXfer$Reply" as a |type_hint| |
-/// |
-Packet* Packet::CreateFromBlob(debug::Blob* message, const char* type_hint) { |
- if (packet_factory_.size() == 0) |
- InitFactory(); |
- |
- // defferentiate [Xc00020304,0:] from [X05] |
- if ((message->size() > 0) && ('X' == message->Front())) { |
- if (message->size() > 3) |
- return NULL; |
- } |
- |
- message->PopSpacesFromBothEnds(); |
- |
- // Empty message can be a reply to 'm' command, or |
- // can indicate that command is not supported. |
- if ((0 == message->size()) && (NULL == type_hint)) |
- return new EmptyPacket; |
- |
- std::string type; |
- bool general_query = false; |
-/* |
- if (message->size() > 0) |
- general_query = (('g' == message->Front()) || ('Q' == message->Front())); |
- if (message->HasPrefix("qC") || message->HasPrefix("QC")) |
- general_query = false; |
-*/ |
- |
- if (NULL != type_hint) { |
- type = type_hint; |
- } else { |
- while (message->size() != 0) { |
- char c = message->Front(); |
- message->PopFront(); |
- if (general_query && ((0 == c) || (':' == c))) |
- break; |
- type.append(1, c); |
- |
- // Commands starting from 'q' or 'Q' are 'general query', and full command |
- // name is terminated by ':' or <eom>. |
- // All other commands have no termination, i.e. they are prefixes, |
- // and they should be looked up as we scan characters. The shortest command |
- // to match wins. |
- if (!general_query) { |
- if (packet_factory_.find(type) != packet_factory_.end()) |
- break; |
- } |
- } |
- } |
- |
- Packet* packet_template = packet_factory_[type]; |
- if (NULL != packet_template) { |
- Packet* packet = packet_template->Create(); |
- if (NULL != packet) { |
- message->PopMatchingCharsFromFront(" :"); |
- if (packet->FromBlob(type, message)) |
- return packet; |
- else |
- delete packet; |
- } |
- } |
- return NULL; |
-} |
- |
-//----------------------------------------------------------// |
-void EmptyPacket::AcceptVisitor(PacketVisitor* vis) { |
- vis->Visit(this); |
-} |
- |
-Packet* EmptyPacket::Create() const { |
- return new EmptyPacket; |
-} |
- |
-bool EmptyPacket::FromBlob(const std::string& type, debug::Blob* message) { |
- return true; |
-} |
- |
-void EmptyPacket::ToBlob(debug::Blob* message) const { |
- message->Clear(); |
-} |
- |
-//----------------------------------------------------------// |
-Packet* QuerySupportedCommand::Create() const { |
- return new QuerySupportedCommand; |
-} |
- |
-void QuerySupportedCommand::AcceptVisitor(PacketVisitor* vis) { |
- vis->Visit(this); |
-} |
- |
-void QuerySupportedCommand::AddFeature(const std::string& name, |
- const std::string& value) { |
- features_.push_back(std::pair<std::string, std::string>(name, value)); |
-} |
- |
-bool QuerySupportedCommand::FromBlob(const std::string& type, |
- debug::Blob* message) { |
- std::deque<debug::Blob> statements; |
- message->Split(";", &statements); |
- std::deque<debug::Blob>::iterator it = statements.begin(); |
- while (it != statements.end()) { |
- std::deque<debug::Blob> tokens; |
- it->Split("=", &tokens); |
- it++; |
- RemoveSpacesFromBothEnds(&tokens); |
- if (tokens.size() >= 2) { |
- AddFeature(tokens[0].ToString(), tokens[1].ToString()); |
- } else if (tokens.size() > 0) { |
- debug::Blob& name = tokens[0]; |
- if (name.size() > 0) { |
- char last_char = name.Back(); |
- name.PopBack(); |
- std::string value; |
- value.append(1, last_char); |
- AddFeature(name.ToString(), value); |
- } |
- } |
- } |
- return true; |
-} |
- |
-size_t QuerySupportedCommand::GetFeaturesNum() const { |
- return features_.size(); |
-} |
- |
-std::string QuerySupportedCommand::GetFeatureName(size_t pos) const { |
- if (pos >= GetFeaturesNum()) |
- return ""; |
- return features_[pos].first; |
-} |
- |
-std::string QuerySupportedCommand::GetFeature(const std::string& name) const { |
- for (size_t i = 0; i < GetFeaturesNum(); i++) { |
- if (name == GetFeatureName(i)) |
- return features_[i].second; |
- } |
- return ""; |
-} |
- |
-void QuerySupportedCommand::SaveFeaturesToBlob(debug::Blob* message) const { |
- size_t num = features_.size(); |
- for (size_t i = 0; i < num; i++ ) { |
- const std::pair<std::string, std::string>& feature = features_[i]; |
- if (0 != i) |
- message->Append(";"); |
- message->Append(feature.first); |
- if (("+" != feature.second) && ("-" != feature.second) && ("?" != feature.second)) |
- message->Append("="); |
- message->Append(feature.second); |
- } |
-} |
- |
-void QuerySupportedCommand::ToBlob(debug::Blob* message) const { |
- message->Append("qSupported:"); |
- SaveFeaturesToBlob(message); |
-} |
- |
-//----------------------------------------------------------// |
-Packet* QuerySupportedReply::Create() const { |
- return new QuerySupportedReply; |
-} |
- |
-void QuerySupportedReply::AcceptVisitor(PacketVisitor* vis) { |
- vis->Visit(this); |
-} |
- |
-void QuerySupportedReply::ToBlob(debug::Blob* message) const { |
- SaveFeaturesToBlob(message); |
-} |
- |
-//----------------------------------------------------------// |
-StopReply::StopReply() |
- : stop_reason_(STILL_RUNNING), |
- signal_number_(0), |
- exit_code_(0), |
- pid_(0) { |
-} |
- |
-StopReply :: StopReply(StopReason stop_reason) |
- : stop_reason_(stop_reason), |
- signal_number_(0), |
- exit_code_(0), |
- pid_(0) { |
-} |
- |
-Packet* StopReply::Create() const { |
- return new StopReply(stop_reason_); |
-} |
- |
-void StopReply::AcceptVisitor(PacketVisitor* vis) { |
- vis->Visit(this); |
-} |
- |
-bool StopReply::FromBlob(const std::string& type, debug::Blob* message) { |
- if ("S" == type) { |
- stop_reason_ = SIGNALED; |
- std::string s = message->ToString(); |
- signal_number_ = message->PopInt8FromFront(); |
- } else if ("W" == type) { |
- stop_reason_ = StopReply::EXITED; |
- exit_code_ = message->PopInt8FromFront(); |
- } else if ("X" == type) { |
- stop_reason_ = StopReply::TERMINATED; |
- signal_number_ = message->PopInt8FromFront(); |
- } else if ("O" == type) { |
- stop_reason_ = StopReply::STILL_RUNNING; |
- } else { |
- return false; |
- } |
- |
- if (("W" == type) || ("X" == type)) { |
- message->PopMatchingCharsFromFront(";"); |
- std::deque<debug::Blob> tokens; |
- message->Split(":", &tokens); |
- if ((tokens.size() >= 2) && (tokens[0] == "process")) { |
- std::string s = tokens[1].ToString(); |
- pid_ = tokens[1].PopInt32FromFront(); |
- } |
- } |
- |
- return true; |
-} |
- |
-void StopReply::ToBlob(debug::Blob* message) const { |
- message->Clear(); |
- switch (stop_reason_) { |
- case SIGNALED: { |
- message->Format("S%0.2x", signal_number_); |
- break; |
- } |
- case TERMINATED: { |
- message->Format("X%0.2x;process:%x", signal_number_, pid_); |
- break; |
- } |
- case EXITED: { |
- message->Format("W%0.2x;process:%x", exit_code_, pid_); |
- break; |
- } |
- case STILL_RUNNING: { |
- *message = "O"; |
- break; |
- } |
- } |
-} |
- |
-//------------------------------------------------// |
-ReadMemoryCommand::ReadMemoryCommand() |
- : addr_(0), |
- num_of_bytes_(0) { |
-} |
- |
-Packet* ReadMemoryCommand::Create() const { |
- return new ReadMemoryCommand; |
-} |
- |
-void ReadMemoryCommand::AcceptVisitor(PacketVisitor* vis) { |
- vis->Visit(this); |
-} |
- |
-bool ReadMemoryCommand::FromBlob(const std::string& type, |
- debug::Blob* message) { |
-// example: H>[mcffffff80,40] (with first 'm' removed) |
- std::deque<debug::Blob> tokens; |
- message->Split(",", &tokens); |
- if (tokens.size() < 2) |
- return false; |
- |
- addr_ = tokens[0].PopInt64FromFront(); |
- num_of_bytes_ = static_cast<int>(tokens[1].PopInt32FromFront()); |
- return true; |
-} |
- |
-void ReadMemoryCommand::ToBlob(debug::Blob* message) const { |
- message->Format("m%I64x,%x", addr_, num_of_bytes_); |
-} |
- |
-WriteMemoryCommand::WriteMemoryCommand() |
- : addr_(0) { |
-} |
- |
-Packet* WriteMemoryCommand::Create() const { |
- return new WriteMemoryCommand; |
-} |
- |
-void WriteMemoryCommand::AcceptVisitor(PacketVisitor* vis) { |
- vis->Visit(this); |
-} |
- |
-bool WriteMemoryCommand::FromBlob(const std::string& type, debug::Blob* message) { |
- // example: H>[Mc00020304,1:8b] |
- std::deque<debug::Blob> tokens; |
- message->Split(",", &tokens); |
- if (tokens.size() < 2) |
- return false; |
- |
- addr_ = tokens[0].PopInt64FromFront(); |
- debug::Blob len_and_data = tokens[1]; |
- len_and_data.Split(":", &tokens); |
- if (tokens.size() < 2) |
- return false; |
- return data_.LoadFromHexString(tokens[1].ToString()); |
-} |
- |
-void WriteMemoryCommand::ToBlob(debug::Blob* message) const { |
- std::string hex_blob = data_.ToHexString(); |
- message->Format("M%I64x,%x:%s", |
- addr_, |
- data_.size(), |
- hex_blob.c_str()); |
-} |
- |
-Packet* BlobReply::Create() const { |
- return new BlobReply; |
-} |
- |
-void BlobReply::AcceptVisitor(PacketVisitor* vis) { |
- vis->Visit(this); |
-} |
- |
-bool BlobReply::FromBlob(const std::string& type, debug::Blob* message) { |
- return data_.LoadFromHexString(message->ToString()); |
-} |
- |
-void BlobReply::ToBlob(debug::Blob* message) const { |
- *message = data_.ToHexString(false); |
-} |
- |
-bool WriteRegistersCommand::FromBlob(const std::string& type, |
- debug::Blob* message) { |
- return data_.LoadFromHexString(message->ToString()); |
-} |
- |
-void WriteRegistersCommand::ToBlob(debug::Blob* message) const { |
- *message = "G"; |
- message->Append(data_.ToHexString(false)); |
-} |
- |
-bool SetCurrentThreadCommand::FromBlob(const std::string& type, debug::Blob* message) { |
- if ((message->size() > 0) && |
- ('-' == message->GetAt(0)) && |
- ('1' == message->GetAt(1))) |
- thread_id_ = -1; // all threads |
- else |
- thread_id_ = message->PopInt32FromFront(); |
- return true; |
-} |
- |
-void SetCurrentThreadCommand::ToBlob(debug::Blob* message) const { |
- if (FOR_READ == subtype_) |
- *message = "Hg"; |
- else |
- *message = "Hc"; |
- |
- if (0 == thread_id_) { |
- message->Append("0"); |
- } else if (-1 == thread_id_) { |
- message->Append("-1"); |
- } else { |
- debug::Blob tmp; |
- tmp.Format("%x", thread_id_); |
- message->Append(tmp); |
- } |
-} |
- |
-const char* QXferFeaturesReadCommand::kPrefix = "qXfer:features:read:"; |
- |
-QXferFeaturesReadCommand::QXferFeaturesReadCommand() |
- : offset_(0), |
- length_(0) { |
-} |
- |
-bool QXferFeaturesReadCommand::FromBlob(const std::string& type, |
- debug::Blob* message) { |
- // example: target.xml:0,7ca |
- debug::Blob file_name = message->PopBlobFromFrontUnilChars(":"); |
- debug::Blob offs = message->PopBlobFromFrontUnilChars(","); |
- |
- file_name_ = file_name.ToString(); |
- offset_ = offs.PopInt32FromFront(); |
- length_ = message->PopInt32FromFront(); |
- return true; |
-} |
- |
-void QXferFeaturesReadCommand::ToBlob(debug::Blob* message) const { |
- message->Format("%s%s:%x,%x", kPrefix, file_name_.c_str(), offset_, length_); |
-} |
- |
-bool QXferReply::FromBlob(const std::string& type, debug::Blob* message) { |
- if (message->size() < 1) |
- return false; |
- char cmd = message->PopFront(); |
- eom_ = ('l' == cmd); |
- body_ = message->ToString(); |
- return true; |
-} |
- |
-void QXferReply::ToBlob(debug::Blob* message) const { |
- message->Format((eom_ ? "l%s" : "m%s"), body_.c_str()); |
-} |
- |
-bool GetThreadInfoCommand::FromBlob(const std::string& type, |
- debug::Blob* message) { |
- get_more_ = ("qsThreadInfo" == type); |
- return true; |
-} |
- |
-void GetThreadInfoCommand::ToBlob(debug::Blob* message) const { |
- if (get_more_) |
- *message = "qsThreadInfo"; |
- else |
- *message = "qfThreadInfo"; |
-} |
- |
-bool GetThreadInfoReply::FromBlob(const std::string& type, debug::Blob* message) { |
- if (message->size() < 1) |
- return false; |
- char cmd = message->PopFront(); |
- eom_ = ('l' == cmd); |
- |
- std::deque<debug::Blob> tokens; |
- message->Split(",", &tokens); |
- |
- for (size_t i = 0; i < tokens.size(); i++) { |
- u_int32_t id = tokens[i].PopInt32FromFront(); |
- threads_ids_.push_back(static_cast<int>(id)); |
- } |
- return true; |
-} |
- |
-void GetThreadInfoReply::ToBlob(debug::Blob* message) const { |
- if (eom_ || (0 == threads_ids_.size())) |
- *message = "l"; |
- else |
- *message = "m"; |
- size_t num = threads_ids_.size(); |
- for (size_t i = 0; i < num; i++) { |
- debug::Blob tmp; |
- tmp.Format("%x", threads_ids_[i]); |
- message->Append(tmp); |
- if ((i + 1) != num) |
- message->Append(","); |
- } |
-} |
-} // namespace rsp |
- |
-namespace { |
-bool HexStringToInt(const std::string& str, int* number) { |
- debug::Blob blob; |
- if (!blob.LoadFromHexString(str)) |
- return false; |
- |
- if (NULL != number) |
- *number = blob.ToInt(); |
- return true; |
-} |
- |
-void RemoveSpacesFromBothEnds(std::deque<debug::Blob>* tokens) { |
- std::deque<debug::Blob>::iterator it = tokens->begin(); |
- while (it != tokens->end()) { |
- debug::Blob& token = *it++; |
- token.PopSpacesFromBothEnds(); |
- } |
-} |
- |
-void InitFactory() { |
- packet_factory_["qSupported"] = new rsp::QuerySupportedCommand; |
- packet_factory_["qSupported$Reply"] = new rsp::QuerySupportedReply; |
- packet_factory_["?"] = new rsp::GetStopReasonCommand; |
- packet_factory_["S"] = new rsp::StopReply(rsp::StopReply::SIGNALED); |
- packet_factory_["X"] = new rsp::StopReply(rsp::StopReply::TERMINATED); |
- packet_factory_["W"] = new rsp::StopReply(rsp::StopReply::EXITED); |
- packet_factory_["O"] = new rsp::StopReply(rsp::StopReply::STILL_RUNNING); |
- packet_factory_["m"] = new rsp::ReadMemoryCommand; |
- packet_factory_["M"] = new rsp::WriteMemoryCommand; |
- packet_factory_["blob$Reply"] = new rsp::BlobReply; |
- packet_factory_["g"] = new rsp::ReadRegistersCommand; |
- packet_factory_["G"] = new rsp::WriteRegistersCommand; |
- packet_factory_["E"] = new rsp::ErrorReply; |
- packet_factory_["OK"] = new rsp::OkReply; |
- packet_factory_["Hg"] = |
- new rsp::SetCurrentThreadCommand(rsp::SetCurrentThreadCommand::FOR_READ); |
- packet_factory_["Hc"] = |
- new rsp::SetCurrentThreadCommand(rsp::SetCurrentThreadCommand::FOR_CONTINUE); |
- packet_factory_["qC"] = new rsp::GetCurrentThreadCommand; |
- packet_factory_["QC"] = new rsp::GetCurrentThreadReply; |
- packet_factory_["c"] = new rsp::ContinueCommand; |
- packet_factory_["s"] = new rsp::StepCommand; |
- packet_factory_["T"] = new rsp::IsThreadAliveCommand; |
- packet_factory_["qXfer:features:read:"] = new rsp::QXferFeaturesReadCommand; |
- packet_factory_["qXfer$Reply"] = new rsp::QXferReply; |
- packet_factory_["qfThreadInfo"] = new rsp::GetThreadInfoCommand; |
- packet_factory_["qsThreadInfo"] = new rsp::GetThreadInfoCommand; |
- packet_factory_["GetThreadInfo$Reply"] = new rsp::GetThreadInfoReply; |
-} |
-} // namespace |