ROSE  0.9.12.28
BinaryDebugger.h
1 #ifndef ROSE_BinaryAnalysis_Debugger_H
2 #define ROSE_BinaryAnalysis_Debugger_H
3 
4 #include <BitFlags.h>
5 #include <boost/noncopyable.hpp>
6 #include <boost/filesystem.hpp>
7 #include <Disassembler.h>
8 #include <Sawyer/BitVector.h>
9 
10 namespace Rose {
11 namespace BinaryAnalysis {
12 
15 
19 class Debugger: private boost::noncopyable, public Sawyer::SharedObject {
20 public:
23 
25  enum DetachMode {
26  KILL,
30  };
31 
33  enum Flag {
34  ATTACH = 0x00000001,
35  REDIRECT_INPUT = 0x00000002,
36  REDIRECT_OUTPUT = 0x00000004,
37  REDIRECT_ERROR = 0x00000008,
38  CLOSE_FILES = 0x00000010,
39  DEFAULT_FLAGS = 0x00000013
40  };
41 
45  class Specimen {
46  BitFlags<Flag> flags_; // operational flags
47 
48  // Members for running a program
49  boost::filesystem::path program_; // ;full path of executable program
50  std::vector<std::string> arguments_; // command-line arguments of executable program
51  boost::filesystem::path workingDirectory_; // name or working directory, or use CWD if empty
52 
53  // Members for attaching to a process
54  int pid_; // process ID (int instead of pid_t for portability)
55 
56  public:
59  : pid_(-1) {}
60 
62  Specimen(int pid) /*implicit*/
63  : flags_(DEFAULT_FLAGS), pid_(pid) {}
64 
66  Specimen(const boost::filesystem::path &name) /*implicit*/
67  : flags_(DEFAULT_FLAGS), program_(name), pid_(-1) {}
68 
70  Specimen(const boost::filesystem::path &name, const std::vector<std::string> &args)
71  : flags_(DEFAULT_FLAGS), program_(name), arguments_(args), pid_(-1) {}
72 
74  Specimen(const std::vector<std::string> &nameAndArgs) /*implicit*/
75  : flags_(DEFAULT_FLAGS), program_(nameAndArgs.front()),
76  arguments_(nameAndArgs.begin()+1, nameAndArgs.end()), pid_(-1) {
77  }
78 
79  public:
86  boost::filesystem::path program() const {
87  return program_;
88  }
89  void program(const boost::filesystem::path &name) {
90  program_ = name;
91  pid_ = -1;
92  }
101  const std::vector<std::string>& arguments() const {
102  return arguments_;
103  }
104  void arguments(const std::vector<std::string> &args) {
105  arguments_ = args;
106  }
116  boost::filesystem::path workingDirectory() const {
117  return workingDirectory_;
118  }
119  void workingDirectory(const boost::filesystem::path &name) {
120  workingDirectory_ = name;
121  }
129  const BitFlags<Flag>& flags() const {
130  return flags_;
131  }
133  return flags_;
134  }
143  int process() const {
144  return pid_;
145  }
146  void process(int pid) {
147  pid_ = pid;
148  program_.clear();
149  }
153  void print(std::ostream &out) const;
154  };
155 
156 private:
158  enum RegPageStatus { REGPAGE_NONE, REGPAGE_REGS, REGPAGE_FPREGS };
159 
160  Specimen specimen_; // description of specimen being debugged
161  int child_; // process being debugged (int, not pid_t, for Windows portability)
162  DetachMode howDetach_; // how to detach from the subordinate
163  int wstat_; // last status from waitpid
164  AddressIntervalSet breakpoints_; // list of breakpoint addresses
165  int sendSignal_; // pending signal
166  UserRegDefs userRegDefs_; // how registers map to user_regs_struct in <sys/user.h>
167  UserRegDefs userFpRegDefs_; // how registers map to user_fpregs_struct in <sys/user.h>
168  size_t kernelWordSize_; // cached width in bits of kernel's words
169  uint8_t regsPage_[512]; // latest register information read from subordinate
170  RegPageStatus regsPageStatus_; // what are the contents of regPage_?
171  Disassembler *disassembler_; // how to disassemble instructions
172 
173  //----------------------------------------
174  // Real constructors
175  //----------------------------------------
176 protected:
177  Debugger()
178  : child_(0), howDetach_(KILL), wstat_(-1), sendSignal_(0), kernelWordSize_(0), regsPageStatus_(REGPAGE_NONE),
179  disassembler_(NULL) {
180  init();
181  }
182 
184  explicit Debugger(const Specimen &specimen)
185  : child_(0), howDetach_(KILL), wstat_(-1), sendSignal_(0), kernelWordSize_(0), regsPageStatus_(REGPAGE_NONE),
186  disassembler_(NULL) {
187  init();
188  attach(specimen);
189  }
190 
191 public:
192  ~Debugger() {
193  detach();
194  }
195 
196  //----------------------------------------
197  // Static allocating constructors
198  //----------------------------------------
199 public:
201  static Ptr instance() {
202  return Ptr(new Debugger);
203  }
204 
206  static Ptr instance(const Specimen &specimen) {
207  return Ptr(new Debugger(specimen));
208  }
209 
210  //----------------------------------------
211  // Attaching to subordinate
212  //----------------------------------------
213 public:
215  void attach(const Specimen&);
216 
218  int isAttached() { return child_; }
219 
221  void detach();
222 
224  void terminate();
225 
226  //----------------------------------------
227  // Operations on a subordinate
228  //----------------------------------------
229 public:
231  void executionAddress(rose_addr_t va);
232 
234  rose_addr_t executionAddress();
235 
237  void setBreakpoint(const AddressInterval&);
238 
240  void clearBreakpoint(const AddressInterval&);
241 
243  void clearBreakpoints() { breakpoints_.clear(); }
244 
246  void singleStep();
247 
249  void runToBreakpoint();
250 
255  void runToSyscall();
256 
259  size_t kernelWordSize();
260 
270 
276  Sawyer::Container::BitVector readMemory(rose_addr_t va, size_t nBytes, ByteOrder::Endianness order);
277 
282  size_t readMemory(rose_addr_t va, size_t nBytes, uint8_t *buffer);
283 
285  bool isTerminated();
286 
288  std::string howTerminated();
289 
291  const RegisterDictionary* registerDictionary() const;
292 
295  return disassembler_;
296  }
297 
299  int waitpidStatus() const { return wstat_; }
300 
301 private:
302  // Initialize tables during construction
303  void init();
304 
305  // Wait for subordinate or throw on error
306  void waitForChild();
307 
308  // Open /dev/null with the specified flags as the indicated file descriptor, closing what was previously on that
309  // descriptor. If an error occurs, the targetFd is closed anyway.
310  void devNullTo(int targetFd, int openFlags);
311 };
312 
313 std::ostream& operator<<(std::ostream&, const Debugger::Specimen&);
314 
315 } // namespace
316 } // namespace
317 
318 #endif
Close all file descriptors > 2.
void print(std::ostream &out) const
Print some basic info about the specimen.
const std::vector< std::string > & arguments() const
Property: Program command-line arguments.
int isAttached()
Returns true if attached to a subordinate.
void clearBreakpoints()
Remove all breakpoints.
void singleStep()
Execute one instruction.
Attach to existing process.
Sawyer::Container::BitVector readMemory(rose_addr_t va, size_t nBytes, ByteOrder::Endianness order)
Read subordinate memory as a bit vector.
void workingDirectory(const boost::filesystem::path &name)
Property: Current working directory for running a program.
Debugger(const Specimen &specimen)
Construct a debugger attached to a specimen.
boost::filesystem::path workingDirectory() const
Property: Current working directory for running a program.
DetachMode
How to detach from a process when this object is destroyed.
size_t kernelWordSize()
Obtain and cache kernel's word size in bits.
Specimen(const boost::filesystem::path &name, const std::vector< std::string > &args)
Construct a specimen description for a program with arguments.
static Ptr instance()
Create a debugger object that isn't attached to any subordinate process.
Redirect standard error to /dev/null.
void runToBreakpoint()
Run until the next breakpoint is reached.
Main namespace for the ROSE library.
boost::filesystem::path program() const
Property: Name of executable program to run.
Sawyer::SharedPointer< class Debugger > DebuggerPtr
Shared-ownership pointer to Debugger.
void detach()
Detach from the subordinate.
Sawyer::SharedPointer< Debugger > Ptr
Shared-ownership pointer to Debugger.
Sawyer::Container::BitVector readRegister(RegisterDescriptor)
Read subordinate register.
Reference-counting smart pointer.
Definition: SharedPointer.h:67
int waitpidStatus() const
Returns the last status from a call to waitpid.
Specimen(int pid)
Construct a specimen description for a process.
Specimen()
Default construct an empty specimen descriptor.
const BitFlags< Flag > & flags() const
Property: Operational flags.
Describes (part of) a physical CPU register.
void terminate()
Terminate the subordinate.
Describes the specimen to be debugged.
int process() const
Property: Process ID.
void arguments(const std::vector< std::string > &args)
Property: Program command-line arguments.
void setBreakpoint(const AddressInterval &)
Set breakpoints.
static Ptr instance(const Specimen &specimen)
Create a debugger and start debugging a specimen.
Disassembler * disassembler() const
Disassembler.
Specimen(const std::vector< std::string > &nameAndArgs)
Construct a specimen description from combined program and arguments.
void clear()
Remove all values.
Definition: IntervalSet.h:487
void process(int pid)
Property: Process ID.
void runToSyscall()
Run until the next system call.
void program(const boost::filesystem::path &name)
Property: Name of executable program to run.
Specimen(const boost::filesystem::path &name)
Construct a specimen description for a program with no arguments.
Base class for reference counted objects.
Definition: SharedObject.h:64
void clearBreakpoint(const AddressInterval &)
Remove breakpoints.
std::string howTerminated()
String describing how the subordinate process terminated.
const RegisterDictionary * registerDictionary() const
Available registers.
Defines registers available for a particular architecture.
Definition: Registers.h:35
Simply detach leaving process in current state.
void attach(const Specimen &)
Attach to a specimen.
bool isTerminated()
Returns true if the subordinate terminated.
Virtual base class for instruction disassemblers.
Definition: Disassembler.h:48
Detach from process and cause it to continue running.
rose_addr_t executionAddress()
Get execution address.
BitFlags< Flag > & flags()
Property: Operational flags.
Flag
Flags controlling operation.