OLD | NEW |
| (Empty) |
1 // Copyright (c) 2011 The Native Client Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 #include "debugger/rsp/rsp_common_replies.h" | |
5 #include "debugger/rsp/rsp_control_packets.h" | |
6 #include "debugger/rsp/rsp_info_packets.h" | |
7 #include "debugger/rsp/rsp_packets.h" | |
8 #include "debugger/rsp/rsp_threads_packets.h" | |
9 | |
10 namespace { | |
11 std::map<std::string, rsp::Packet*> packet_factory_; | |
12 | |
13 /// Pops type field from the front of |message|. | |
14 /// @param[in,out] message RSP packet | |
15 /// @param[in] type_hint optional type hint or NULL | |
16 /// @return string with message type | |
17 std::string PopPacketType(debug::Blob* message, const char* type_hint) { | |
18 if (packet_factory_.size() == 0) | |
19 rsp::Packet::InitPacketFactory(); | |
20 | |
21 // If |type_hint| is supplied, then message don't have type field, | |
22 // and there's no point in trying to find it. | |
23 if (NULL != type_hint) | |
24 return type_hint; | |
25 | |
26 // Most commands have no termination, i.e. they are prefixes, | |
27 // and they should be looked up as we scan characters. The shortest | |
28 // command to match wins. | |
29 std::string type; | |
30 while (message->size() != 0) { | |
31 char c = message->Front(); | |
32 message->PopFront(); | |
33 type.append(1, c); | |
34 if (packet_factory_.find(type) != packet_factory_.end()) | |
35 break; | |
36 } | |
37 // If packet type is terminated by ':', we should pop it off. | |
38 message->PopMatchingBytesFromFront(debug::Blob().FromString(" :")); | |
39 return type; | |
40 } | |
41 } // namespace | |
42 | |
43 namespace rsp { | |
44 Packet* Packet::CreateFromBlob(debug::Blob* message, const char* type_hint) { | |
45 RemoveSpacesFromBothEnds(message); | |
46 | |
47 // Empty message can be a reply to 'm' command, or | |
48 // can indicate that command is not supported. | |
49 if ((0 == message->size()) && (NULL == type_hint)) | |
50 return new EmptyPacket; | |
51 | |
52 // To differentiate [Xc00020304,0:] from [X05] or [X21;process:138c] | |
53 // I.e. we need to detect if it's a 'X' command (write data to memory, where | |
54 // the data is transmitted in binary) or 'X' reply (the process terminated | |
55 // with signal). | |
56 if ((message->size() > 0) && | |
57 ('X' == message->Front()) && | |
58 (message->HasByte(','))) | |
59 return NULL; // we don't support 'X' command. | |
60 | |
61 // To differentiate it from 'O' packet (StopReply). | |
62 if (*message == debug::Blob().FromString("OK")) | |
63 return new OkReply; | |
64 | |
65 std::string type = PopPacketType(message, type_hint); | |
66 if (packet_factory_.find(type) == packet_factory_.end()) | |
67 return NULL; | |
68 | |
69 Packet* packet = packet_factory_[type]->Clone(); | |
70 if ((NULL != packet) && (!packet->FromBlob(type, message))) { | |
71 delete packet; | |
72 packet = NULL; | |
73 } | |
74 return packet; | |
75 } | |
76 | |
77 void Packet::InitPacketFactory() { | |
78 packet_factory_["qSupported"] = new rsp::QuerySupportedCommand; | |
79 packet_factory_["qSupported$Reply"] = new rsp::QuerySupportedReply; | |
80 packet_factory_["?"] = new rsp::GetStopReasonCommand; | |
81 packet_factory_["S"] = new rsp::StopReply(rsp::StopReply::SIGNALED); | |
82 packet_factory_["X"] = new rsp::StopReply(rsp::StopReply::TERMINATED); | |
83 packet_factory_["W"] = new rsp::StopReply(rsp::StopReply::EXITED); | |
84 packet_factory_["O"] = new rsp::StopReply(rsp::StopReply::STILL_RUNNING); | |
85 packet_factory_["m"] = new rsp::ReadMemoryCommand; | |
86 packet_factory_["M"] = new rsp::WriteMemoryCommand; | |
87 packet_factory_["blob$Reply"] = new rsp::BlobReply; | |
88 packet_factory_["g"] = new rsp::ReadRegistersCommand; | |
89 packet_factory_["G"] = new rsp::WriteRegistersCommand; | |
90 packet_factory_["E"] = new rsp::ErrorReply; | |
91 packet_factory_["OK"] = new rsp::OkReply; | |
92 packet_factory_["Hg"] = | |
93 new rsp::SetCurrentThreadCommand(rsp::SetCurrentThreadCommand::FOR_READ); | |
94 packet_factory_["Hc"] = | |
95 new rsp::SetCurrentThreadCommand( | |
96 rsp::SetCurrentThreadCommand::FOR_CONTINUE); | |
97 packet_factory_["qC"] = new rsp::GetCurrentThreadCommand; | |
98 packet_factory_["QC"] = new rsp::GetCurrentThreadReply; | |
99 packet_factory_["c"] = new rsp::ContinueCommand; | |
100 packet_factory_["s"] = new rsp::StepCommand; | |
101 packet_factory_["T"] = new rsp::IsThreadAliveCommand; | |
102 packet_factory_["qXfer:features:read:"] = new rsp::QXferFeaturesReadCommand; | |
103 packet_factory_["qXfer$Reply"] = new rsp::QXferReply; | |
104 packet_factory_["qfThreadInfo"] = new rsp::GetThreadInfoCommand; | |
105 packet_factory_["qsThreadInfo"] = new rsp::GetThreadInfoCommand; | |
106 packet_factory_["GetThreadInfo$Reply"] = new rsp::GetThreadInfoReply; | |
107 packet_factory_["qOffsets"] = new rsp::GetOffsetsCommand; | |
108 packet_factory_["qOffsets$Reply"] = new rsp::GetOffsetsReply; | |
109 } | |
110 | |
111 void Packet::FreePacketFactory() { | |
112 std::map<std::string, rsp::Packet*>::const_iterator it = | |
113 packet_factory_.begin(); | |
114 while (it != packet_factory_.end()) { | |
115 delete it->second; | |
116 ++it; | |
117 } | |
118 packet_factory_.clear(); | |
119 } | |
120 } // namespace rsp | |
121 | |
OLD | NEW |