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 #ifndef DEBUGGER_RSP_RSP_PACKETS_H_ | |
5 #define DEBUGGER_RSP_RSP_PACKETS_H_ | |
6 | |
7 #include <deque> | |
8 #include <map> | |
9 #include <string> | |
10 #include <vector> | |
11 #include "debugger/base/debug_blob.h" | |
12 #include "debugger/rsp/rsp_blob_utils.h" | |
13 | |
14 // GDB RSP (remote serial protocol) description: | |
15 // http://sources.redhat.com/gdb/current/onlinedocs/gdb.html#Remote-Protocol | |
16 | |
17 namespace rsp { | |
18 static const size_t kMaxRspPacketSize = 0x7cf; | |
19 | |
20 class PacketVisitor; | |
21 class EmptyPacket; | |
22 class QuerySupportedCommand; | |
23 class QuerySupportedReply; | |
24 class GetStopReasonCommand; | |
25 class StopReply; | |
26 class ReadMemoryCommand; | |
27 class WriteMemoryCommand; | |
28 class BlobReply; | |
29 class ReadRegistersCommand; | |
30 class WriteRegistersCommand; | |
31 class ErrorReply; | |
32 class OkReply; | |
33 class SetCurrentThreadCommand; | |
34 class GetCurrentThreadCommand; | |
35 class GetCurrentThreadReply; | |
36 class ContinueCommand; | |
37 class StepCommand; | |
38 class IsThreadAliveCommand; | |
39 class QXferFeaturesReadCommand; | |
40 class QXferReply; | |
41 class GetOffsetsCommand; | |
42 class GetOffsetsReply; | |
43 class GetThreadInfoCommand; | |
44 class GetThreadInfoReply; | |
45 | |
46 /// Root class for all RSP packets. | |
47 class Packet { | |
48 public: | |
49 Packet() {} | |
50 virtual ~Packet() {} | |
51 | |
52 /// Creates a new object on the heap. | |
53 /// Used by |factory_| in the |CreateFromBlob| method. | |
54 virtual Packet* Clone() const = 0; | |
55 | |
56 /// Create a RSP representation for the packet. | |
57 /// @param[out] message destination for the serialized packet | |
58 virtual void ToBlob(debug::Blob* message) const = 0; | |
59 | |
60 /// Fills content of the packet from |message|. | |
61 /// @param[in] type type of the message, for example "G" for write general | |
62 /// registers packet | |
63 /// @param[in] message serial RSP representation | |
64 /// Call to this method can modify |message|. | |
65 virtual bool FromBlob(const std::string& type, | |
66 debug::Blob* message) = 0; | |
67 | |
68 /// This method calls back the appropriate vis->Visit() method. | |
69 virtual void AcceptVisitor(PacketVisitor* vis) {} | |
70 | |
71 /// Creates an appropriate object from serial RSP representation. | |
72 /// @param[in] message serial RSP representation | |
73 /// @param[in] type_hint hint to help parser | |
74 /// | |
75 /// Note: this method modifies |message|. | |
76 /// Note: returned obj shall be deleted by caller. | |
77 /// | |
78 /// Why |type_hint|? Because some RSP packets don't carry type field. | |
79 /// Examples: | |
80 /// 1. replies to 'm' (read memory) command: | |
81 /// H>[mc000202e0,12] | |
82 /// T>[554889e583ec204c01fc897dec8975e8c745] | |
83 /// => caller should supply "blob$Reply" as a |type_hint| | |
84 /// | |
85 /// 2. replies to 'g' (read registers) command: | |
86 /// H>[g] | |
87 /// T>[00000000000000000000000000000000d85123... | |
88 /// => caller should supply "blob$Reply" as a |type_hint| | |
89 /// | |
90 /// 3. replies to 'qSupported' command: | |
91 /// H>[qSupported:xmlRegisters=i386;qRelocInsn+] | |
92 /// T>[PacketSize=7cf;qXfer:libraries:read+;qXfer:features:read+] | |
93 /// => caller should supply "qSupported$Reply" as a |type_hint| | |
94 /// | |
95 /// 4. replies to 'qXfer' command: | |
96 /// => caller should supply "qXfer$Reply" as a |type_hint| | |
97 static Packet* CreateFromBlob(debug::Blob* message, | |
98 const char* type_hint); | |
99 /// Creates packet factory. | |
100 static void InitPacketFactory(); | |
101 | |
102 /// Removes packet factory. | |
103 /// Shall be called when |CreateFromBlob| is not needed anymore, | |
104 /// otherwise memory will be leaked. | |
105 static void FreePacketFactory(); | |
106 }; | |
107 | |
108 // Visitor pattern: | |
109 // http://en.wikipedia.org/wiki/Visitor_pattern | |
110 class PacketVisitor { | |
111 public: | |
112 virtual ~PacketVisitor() {} | |
113 | |
114 virtual void Visit(EmptyPacket* packet) {} | |
115 virtual void Visit(QuerySupportedCommand* packet) {} | |
116 virtual void Visit(QuerySupportedReply* packet) {} | |
117 virtual void Visit(GetStopReasonCommand* packet) {} | |
118 virtual void Visit(StopReply* packet) {} | |
119 virtual void Visit(ReadMemoryCommand* packet) {} | |
120 virtual void Visit(WriteMemoryCommand* packet) {} | |
121 virtual void Visit(BlobReply* packet) {} | |
122 virtual void Visit(ReadRegistersCommand* packet) {} | |
123 virtual void Visit(WriteRegistersCommand* packet) {} | |
124 virtual void Visit(ErrorReply* packet) {} | |
125 virtual void Visit(OkReply* packet) {} | |
126 virtual void Visit(SetCurrentThreadCommand* packet) {} | |
127 virtual void Visit(GetCurrentThreadCommand* packet) {} | |
128 virtual void Visit(GetCurrentThreadReply* packet) {} | |
129 virtual void Visit(ContinueCommand* packet) {} | |
130 virtual void Visit(StepCommand* packet) {} | |
131 virtual void Visit(IsThreadAliveCommand* packet) {} | |
132 virtual void Visit(QXferFeaturesReadCommand* packet) {} | |
133 virtual void Visit(QXferReply* packet) {} | |
134 virtual void Visit(GetThreadInfoCommand* packet) {} | |
135 virtual void Visit(GetThreadInfoReply* packet) {} | |
136 virtual void Visit(GetOffsetsCommand* packet) {} | |
137 virtual void Visit(GetOffsetsReply* packet) {} | |
138 }; | |
139 | |
140 /// This class is used in |packet_cast| casting template. | |
141 class TypingPacketVisitor : public PacketVisitor { | |
142 public: | |
143 TypingPacketVisitor() : type_(0) {} | |
144 | |
145 virtual void Visit(EmptyPacket* packet) { type_ = 1;} | |
146 virtual void Visit(QuerySupportedCommand* packet) { type_ = 2;} | |
147 virtual void Visit(QuerySupportedReply* packet) { type_ = 3;} | |
148 virtual void Visit(GetStopReasonCommand* packet) { type_ = 4;} | |
149 virtual void Visit(StopReply* packet) { type_ = 5;} | |
150 virtual void Visit(ReadMemoryCommand* packet) { type_ = 6;} | |
151 virtual void Visit(WriteMemoryCommand* packet) { type_ = 7;} | |
152 virtual void Visit(BlobReply* packet) { type_ = 8;} | |
153 virtual void Visit(ReadRegistersCommand* packet) { type_ = 9;} | |
154 virtual void Visit(WriteRegistersCommand* packet) { type_ = 10;} | |
155 virtual void Visit(ErrorReply* packet) { type_ = 11;} | |
156 virtual void Visit(OkReply* packet) { type_ = 12;} | |
157 virtual void Visit(SetCurrentThreadCommand* packet) { type_ = 13;} | |
158 virtual void Visit(GetCurrentThreadCommand* packet) { type_ = 14;} | |
159 virtual void Visit(GetCurrentThreadReply* packet) { type_ = 15;} | |
160 virtual void Visit(ContinueCommand* packet) { type_ = 16;} | |
161 virtual void Visit(StepCommand* packet) { type_ = 17;} | |
162 virtual void Visit(IsThreadAliveCommand* packet) { type_ = 18;} | |
163 virtual void Visit(QXferFeaturesReadCommand* packet) { type_ = 19;} | |
164 virtual void Visit(QXferReply* packet) { type_ = 20;} | |
165 virtual void Visit(GetThreadInfoCommand* packet) { type_ = 21;} | |
166 virtual void Visit(GetThreadInfoReply* packet) { type_ = 22;} | |
167 virtual void Visit(GetOffsetsCommand* packet) { type_ = 23;} | |
168 virtual void Visit(GetOffsetsReply* packet) { type_ = 24;} | |
169 | |
170 int type_; | |
171 }; | |
172 | |
173 template <class T> | |
174 T* packet_cast(Packet* obj) { | |
175 if (NULL == obj) | |
176 return NULL; | |
177 | |
178 TypingPacketVisitor vis; | |
179 obj->AcceptVisitor(&vis); | |
180 int obj_type = vis.type_; | |
181 | |
182 T tmp; | |
183 tmp.AcceptVisitor(&vis); | |
184 if (vis.type_ == obj_type) | |
185 return reinterpret_cast<T*>(obj); | |
186 return NULL; | |
187 } | |
188 | |
189 /// Abstract base class for packets types: 'g', '?', 'qC', 's' etc. | |
190 class OneWordPacket : public Packet { | |
191 public: | |
192 explicit OneWordPacket(const std::string& word) : word_(word) {} | |
193 virtual bool FromBlob(const std::string& type, debug::Blob* message) { | |
194 return message->size() == 0; | |
195 } | |
196 virtual void ToBlob(debug::Blob* message) const { | |
197 message->FromString(word_); | |
198 } | |
199 protected: | |
200 std::string word_; | |
201 }; | |
202 | |
203 /// Abstract base class for these packets classes: | |
204 /// GetCurrentThreadReply | |
205 /// IsThreadAliveCommand | |
206 class WordWithIntPacket : public Packet { | |
207 public: | |
208 explicit WordWithIntPacket(const std::string& word) : word_(word) {} | |
209 | |
210 virtual bool FromBlob(const std::string& type, debug::Blob* message) { | |
211 return PopIntFromFront(message, &value_); | |
212 } | |
213 virtual void ToBlob(debug::Blob* message) const { | |
214 Format(message, "%s%x", word_.c_str(), value_); | |
215 } | |
216 uint32_t value() const { return value_; } | |
217 void set_value(uint32_t x) { value_ = x; } | |
218 | |
219 protected: | |
220 std::string word_; | |
221 uint32_t value_; | |
222 }; | |
223 } // namespace rsp | |
224 | |
225 #endif // DEBUGGER_RSP_RSP_PACKETS_H_ | |
226 | |
OLD | NEW |