ROSE  0.11.109.0
Gdb.h
1 #ifndef ROSE_BinaryAnalysis_Debugger_Gdb_H
2 #define ROSE_BinaryAnalysis_Debugger_Gdb_H
3 #include <featureTests.h>
4 #ifdef ROSE_ENABLE_DEBUGGER_GDB
5 
6 #include <Rose/BinaryAnalysis/Debugger/Base.h>
7 #include <Rose/BinaryAnalysis/Debugger/GdbResponse.h>
8 #include <Rose/Yaml.h>
9 
10 #include <boost/asio.hpp>
11 #include <boost/filesystem.hpp>
12 #include <boost/process.hpp>
13 
14 #include <condition_variable>
15 #include <future>
16 #include <string>
17 #include <thread>
18 
19 namespace Rose {
20 namespace BinaryAnalysis {
21 namespace Debugger {
22 
24 class Gdb: public Base {
25 
27  // Types
29 public:
31  using Ptr = GdbPtr;
32 
34  struct Specimen {
36  boost::filesystem::path gdbName = "gdb-multiarch";
37 
41  boost::filesystem::path executable;
42 
46  struct Remote {
47  std::string host;
48  uint16_t port = 0;
49  } remote;
50  };
51 
52  // Thread-safe FIFO
53  template<class T>
54  class Fifo {
55  public:
56  using Value = T;
57 
58  private:
59  std::condition_variable cond_; // notified by append()
60  std::mutex mutex_; // protects the following data members
61  std::list<Value> items_;
62  bool isClosed_ = false;
63 
64  public:
65  // Append an item to the list
66  void append(const Value &item) {
67  const std::lock_guard<std::mutex> lock(mutex_);
68  items_.push_back(item);
69  cond_.notify_one();
70  }
71 
72  // Remove all items from this FIFO
73  void clear() {
74  const std::lock_guard<std::mutex> lock(mutex_);
75  items_.clear();
76  cond_.notify_all();
77  }
78 
79  // Mark the list as closed. No more items can be appended.
80  void close() {
81  {
82  const std::lock_guard<std::mutex> lock(mutex_);
83  isClosed_ = true;
84  }
85  cond_.notify_all();
86  }
87 
88  // Returns the item from the queue, if any.
89  Sawyer::Optional<Value> nonblockingNext() {
90  const std::lock_guard<std::mutex> lock(mutex_);
91  if (items_.empty()) {
92  return Sawyer::Nothing();
93  } else {
94  Value item = items_.front();
95  items_.pop_front();
96  return item;
97  }
98  }
99 
100  // Blocks until an item can be returned or the queue is closed
101  Sawyer::Optional<Value> blockingNext() {
102  std::unique_lock<std::mutex> lock(mutex_);
103  while (items_.empty() && !isClosed_)
104  cond_.wait(lock);
105  if (items_.empty()) {
106  return Sawyer::Nothing();
107  } else {
108  Value item = items_.front();
109  items_.pop_front();
110  return item;
111  }
112  }
113 
114  // Remvoe all items
115  void reset() {
116  std::lock_guard<std::mutex> lock(mutex_);
117  items_.clear();
118  isClosed_ = false;
119  }
120  };
121 
122  // GDB command response record
123  struct Response {
124  bool hasEndMarker = false;
125 
126  struct ResultRecord {
127  enum ResultClass { EMPTY, DONE, RUNNING, CONNECTED, ERROR, EXIT };
128  ResultClass rclass = EMPTY;
129  std::string token;
130  std::list<Yaml::Node> results;
131  };
132 
133  std::list<ResultRecord> resultRecord;
134  };
135 
136 
138  // Data members
140 private:
141  std::thread gdbThread_;
142  Fifo<std::string> gdbOutput_;
143  boost::asio::io_service ios_;
144  boost::process::async_pipe gdbOutputPipe_;
145  boost::process::opstream gdbInput_;
146  boost::asio::streambuf gdbOutputBuffer_;
147  std::vector<std::pair<std::string, RegisterDescriptor>> registers_;
148  std::list<GdbResponse> responses_; // accumulated responses
149  AddressIntervalSet breakPoints_; // all break points
150  std::map<rose_addr_t, unsigned /*bp_id*/> gdbBreakPoints_; // subset of breakpoints known to GDB
151  std::future<int> exitCodeFuture_; // exit code returned from GDB thread
152  Sawyer::Optional<int> exitCode_; // exit code from the GDB process
153 
155  // Constructors and destructors
157 protected:
158  Gdb();
159 public:
160  ~Gdb();
161 
162 public:
166  static Ptr instance();
167 
171  static Ptr instance(const Specimen&);
172 
174  // Attaching and detaching
176 public:
180  virtual void attach(const Specimen&);
181 
183  // Low-level stuff not often used publically but available nonetheless.
185 public:
192  const std::list<GdbResponse>& sendCommand(const std::string&);
193 
198  std::list<GdbResponse> readRequiredResponses();
199 
204  std::list<GdbResponse> readOptionalResponses();
205 
209  const std::list<GdbResponse>& responses() const;
210 
212  void resetResponses();
213 
217  const std::vector<std::pair<std::string, RegisterDescriptor>>& registerNames() const;
218 
220  // Overrides for methods declared and documented in the super class.
222 public:
223  virtual bool isAttached() override;
224  virtual void detach() override;
225  virtual void terminate() override;
226  virtual std::vector<ThreadId> threadIds() override;
227  virtual void setBreakPoint(const AddressInterval&) override;
228  virtual void clearBreakPoint(const AddressInterval&) override;
229  virtual void clearBreakPoints() override;
230  virtual void singleStep(ThreadId) override;
231  virtual void runToBreakPoint(ThreadId) override;
232  virtual Sawyer::Container::BitVector readRegister(ThreadId, RegisterDescriptor) override;
233  virtual void writeRegister(ThreadId, RegisterDescriptor, const Sawyer::Container::BitVector&) override;
234  virtual void writeRegister(ThreadId, RegisterDescriptor, uint64_t value) override;
235  virtual size_t readMemory(rose_addr_t va, size_t nBytes, uint8_t *buffer) override;
236  virtual std::vector<uint8_t> readMemory(rose_addr_t va, size_t nBytes) override;
237  virtual Sawyer::Container::BitVector readMemory(rose_addr_t va, size_t nBytes, ByteOrder::Endianness order) override;
238  virtual size_t writeMemory(rose_addr_t va, size_t nBytes, const uint8_t *bytes) override;
239  virtual bool isTerminated() override;
240  virtual std::string howTerminated() override;
241 
243  // Supporting functions
245 private:
246  // Read GDB's multi-line response to a command
247  std::list<GdbResponse> readResponseSet(bool required);
248 
249  // Find the index for the GDB register whose major and minor numbers match the specified register.
250  Sawyer::Optional<size_t> findRegisterIndex(RegisterDescriptor) const;
251 
252  // Find the register descriptor for the GDB register whose major and minor numbers match the specified register. Returns
253  // an empty descriptor if not found.
254  RegisterDescriptor findRegister(RegisterDescriptor) const;
255 
256  // True if GDB should handle the break points; false if ROSE should handle the break points.
257  bool gdbHandlesBreakPoints() const;
258 };
259 
260 } // namespace
261 } // namespace
262 } // namespace
263 
264 #endif
265 #endif
ROSE_DLL_API void clear()
Empties the memory pool of all nodes.
Error messages that indicate an abnormal situation from which the program was able to at least partia...
Definition: Message.h:330
Main namespace for the ROSE library.
const char * ResultClass(int64_t)
Convert Rose::BinaryAnalysis::Debugger::Gdb::Response::ResultRecord::ResultClass enum constant to a s...
Sawyer::SharedPointer< Node > Ptr
Reference counting pointer.
Represents no value.
Definition: Optional.h:32