ROSE  0.11.31.0
BinaryDebugger.h
1 #ifndef ROSE_BinaryAnalysis_Debugger_H
2 #define ROSE_BinaryAnalysis_Debugger_H
3 
4 #include <featureTests.h>
5 #ifdef ROSE_ENABLE_BINARY_ANALYSIS
6 
7 #include <BitFlags.h>
8 #include <boost/filesystem.hpp>
9 #include <boost/noncopyable.hpp>
10 #include <boost/regex.hpp>
11 #include <Disassembler.h>
12 #include <Sawyer/BitVector.h>
13 #include <Sawyer/Message.h>
14 #include <Sawyer/Optional.h>
15 #include <Sawyer/Trace.h>
16 
17 namespace Rose {
18 namespace BinaryAnalysis {
19 
22 
26 class Debugger: private boost::noncopyable, public Sawyer::SharedObject {
27 public:
30 
32  enum DetachMode {
33  KILL,
37  };
38 
40  enum Flag {
41  ATTACH = 0x00000001,
42  REDIRECT_INPUT = 0x00000002,
43  REDIRECT_OUTPUT = 0x00000004,
44  REDIRECT_ERROR = 0x00000008,
45  CLOSE_FILES = 0x00000010,
46  DEFAULT_FLAGS = 0x00000013
47  };
48 
52  class Specimen {
53  BitFlags<Flag> flags_; // operational flags
54  unsigned long persona_; // personality(2) flags
55 
56  // Members for running a program
57  boost::filesystem::path program_; // full path of executable program
58  std::vector<std::string> arguments_; // command-line arguments of executable program
59  boost::filesystem::path workingDirectory_; // name or working directory, or use CWD if empty
60  std::vector<boost::regex> clearEnvVars_; // clear environment variables matching these patterns
61  std::map<std::string, std::string> setEnvVars_; // environment variables to be set
62 
63  // Members for attaching to a process
64  int pid_; // process ID (int instead of pid_t for portability)
65 
66  public:
69  : persona_(getPersonality()), pid_(-1) {}
70 
72  Specimen(int pid) /*implicit*/
73  : flags_(DEFAULT_FLAGS), persona_(getPersonality()), pid_(pid) {}
74 
76  Specimen(const boost::filesystem::path &name) /*implicit*/
77  : flags_(DEFAULT_FLAGS), persona_(getPersonality()), program_(name), pid_(-1) {}
78 
80  Specimen(const boost::filesystem::path &name, const std::vector<std::string> &args)
81  : flags_(DEFAULT_FLAGS), persona_(getPersonality()), program_(name), arguments_(args), pid_(-1) {}
82 
84  Specimen(const std::vector<std::string> &nameAndArgs) /*implicit*/
85  : flags_(DEFAULT_FLAGS), persona_(getPersonality()), program_(nameAndArgs.front()),
86  arguments_(nameAndArgs.begin()+1, nameAndArgs.end()), pid_(-1) {
87  }
88 
89  public:
96  boost::filesystem::path program() const {
97  return program_;
98  }
99  void program(const boost::filesystem::path &name) {
100  program_ = name;
101  pid_ = -1;
102  }
111  const std::vector<std::string>& arguments() const {
112  return arguments_;
113  }
114  void arguments(const std::vector<std::string> &args) {
115  arguments_ = args;
116  }
124  void eraseEnvironmentVariable(const std::string&);
125 
131  void eraseMatchingEnvironmentVariables(const boost::regex&);
132 
137 
143  void insertEnvironmentVariable(const std::string &name, const std::string &value);
144 
152  boost::filesystem::path workingDirectory() const {
153  return workingDirectory_;
154  }
155  void workingDirectory(const boost::filesystem::path &name) {
156  workingDirectory_ = name;
157  }
165  const BitFlags<Flag>& flags() const {
166  return flags_;
167  }
169  return flags_;
170  }
180  unsigned long persona() const {
181  return persona_;
182  }
183  void persona(unsigned long bits) {
184  persona_ = bits;
185  }
196  bool randomizedAddresses() const;
197  void randomizedAddresses(bool);
206  int process() const {
207  return pid_;
208  }
209  void process(int pid) {
210  pid_ = pid;
211  program_.clear();
212  }
216  void print(std::ostream &out) const;
217 
218  // Used internally.
219  char** prepareEnvAdjustments() const;
220  };
221 
222 public:
225 private:
227  enum RegPageStatus { REGPAGE_NONE, REGPAGE_REGS, REGPAGE_FPREGS };
228 
229  Specimen specimen_; // description of specimen being debugged
230  int child_; // process being debugged (int, not pid_t, for Windows portability)
231  DetachMode autoDetach_; // how to detach from the subordinate when deleting this debugger
232  int wstat_; // last status from waitpid
233  AddressIntervalSet breakpoints_; // list of breakpoint addresses
234  int sendSignal_; // pending signal
235  UserRegDefs userRegDefs_; // how registers map to user_regs_struct in <sys/user.h>
236  UserRegDefs userFpRegDefs_; // how registers map to user_fpregs_struct in <sys/user.h>
237  size_t kernelWordSize_; // cached width in bits of kernel's words
238  uint8_t regsPage_[512]; // latest register information read from subordinate
239  RegPageStatus regsPageStatus_; // what are the contents of regPage_?
240  Disassembler *disassembler_; // how to disassemble instructions
241  Sawyer::Optional<rose_addr_t> syscallVa_; // address of some executable system call instruction.
242 
243  //----------------------------------------
244  // Real constructors
245  //----------------------------------------
246 protected:
247  Debugger()
248  : child_(0), autoDetach_(KILL), wstat_(-1), sendSignal_(0), kernelWordSize_(0), regsPageStatus_(REGPAGE_NONE),
249  disassembler_(NULL) {
250  init();
251  }
252 
254  explicit Debugger(const Specimen &specimen)
255  : child_(0), autoDetach_(KILL), wstat_(-1), sendSignal_(0), kernelWordSize_(0), regsPageStatus_(REGPAGE_NONE),
256  disassembler_(NULL) {
257  init();
258  attach(specimen);
259  }
260 
261 public:
262  ~Debugger() {
263  detach(autoDetach_);
264  }
265 
266  //----------------------------------------
267  // Static allocating constructors
268  //----------------------------------------
269 public:
271  static Ptr instance() {
272  return Ptr(new Debugger);
273  }
274 
276  static Ptr instance(const Specimen &specimen) {
277  return Ptr(new Debugger(specimen));
278  }
279 
280  //----------------------------------------
281  // Attaching to subordinate
282  //----------------------------------------
283 public:
291  void attach(const Specimen&, Sawyer::Optional<DetachMode> onDelete = Sawyer::Nothing());
295  int isAttached() { return child_; }
296 
302 
304  void terminate();
305 
306  //----------------------------------------
307  // Operations on a subordinate
308  //----------------------------------------
309 public:
311  void executionAddress(rose_addr_t va);
312 
314  rose_addr_t executionAddress();
315 
317  void setBreakpoint(const AddressInterval&);
318 
320  void clearBreakpoint(const AddressInterval&);
321 
323  void clearBreakpoints() { breakpoints_.clear(); }
324 
326  void singleStep();
327 
329  void runToBreakpoint();
330 
335  void runToSyscall();
336 
339 
342  REJECT = 0x00000001,
343  STOP = 0x00000002
344  };
345 
352 
358  template<class Filter>
361  while (!isTerminated()) {
362  rose_addr_t va = executionAddress();
363  FilterAction action = filter(va);
364  if (action.isClear(REJECT))
365  retval.append(va);
366  if (action.isSet(STOP))
367  return retval;
368  singleStep();
369  }
370  return retval;
371  }
372 
375  size_t kernelWordSize();
376 
386 
391  void writeRegister(RegisterDescriptor, uint64_t value);
399  Sawyer::Container::BitVector readMemory(rose_addr_t va, size_t nBytes, ByteOrder::Endianness order);
400 
404  size_t writeMemory(rose_addr_t va, size_t nBytes, const uint8_t *bytes);
405 
409  template<typename T>
410  void writeMemory(rose_addr_t va, const T &value) {
411  size_t n = writeMemory(va, sizeof(T), (const uint8_t*)&value);
412  ASSERT_always_require(n == sizeof(T));
413  }
414 
419  size_t readMemory(rose_addr_t va, size_t nBytes, uint8_t *buffer);
420 
426  std::string readCString(rose_addr_t va, size_t maxBytes = UNLIMITED);
427 
429  bool isTerminated();
430 
432  std::string howTerminated();
433 
435  const RegisterDictionary* registerDictionary() const;
436 
439  return disassembler_;
440  }
441 
443  int waitpidStatus() const { return wstat_; }
444 
446  int remoteSystemCall(int syscallNumber, std::vector<uint64_t> args);
447 
452  int remoteOpenFile(const boost::filesystem::path &fileName, unsigned flags, mode_t mode);
453 
455  int remoteCloseFile(unsigned remoteFd);
456 
460  rose_addr_t remoteMmap(rose_addr_t va, size_t nBytes, unsigned prot, unsigned flags, const boost::filesystem::path&,
461  off_t offset);
462 
463 public:
465  static void initDiagnostics();
466 
467 private:
468  // Initialize tables during construction
469  void init();
470 
471  // Wait for subordinate or throw on error
472  void waitForChild();
473 
474  // Open /dev/null with the specified flags as the indicated file descriptor, closing what was previously on that
475  // descriptor. If an error occurs, the targetFd is closed anyway.
476  void devNullTo(int targetFd, int openFlags);
477 
478  // Get/set personality in a portable way
479  static unsigned long getPersonality();
480  static void setPersonality(unsigned long);
481 
482  // Address of a system call instruction. The initial search can be expensive, so the result is cached.
483  Sawyer::Optional<rose_addr_t> findSystemCall();
484 
485 };
486 
487 std::ostream& operator<<(std::ostream&, const Debugger::Specimen&);
488 
489 } // namespace
490 } // namespace
491 
492 #endif
493 #endif
Close all file descriptors > 2.
void print(std::ostream &out) const
Print some basic info about the specimen.
Records and replays traces.
Definition: Trace.h:262
const std::vector< std::string > & arguments() const
Property: Program command-line arguments.
int remoteSystemCall(int syscallNumber, std::vector< uint64_t > args)
Cause the subordinate to execute a system call.
int isAttached()
Returns true if attached to a subordinate.
void clearBreakpoints()
Remove all breakpoints.
void singleStep()
Execute one instruction.
void append(const Label &label)
Append a label to a trace.
Definition: Trace.h:476
Attach to existing process.
const size_t UNLIMITED(-1)
Effictively unlimited size.
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.
Sawyer::Container::Trace< rose_addr_t > trace()
Run the program and return an execution trace.
Collection of streams.
Definition: Message.h:1606
boost::filesystem::path workingDirectory() const
Property: Current working directory for running a program.
int remoteOpenFile(const boost::filesystem::path &fileName, unsigned flags, mode_t mode)
Cause the subordinate to open a file.
DetachMode
How to detach from a process when the debugger is destroyed.
size_t kernelWordSize()
Obtain and cache kernel's word size in bits.
void eraseMatchingEnvironmentVariables(const boost::regex &)
Remove some environment variables.
Specimen(const boost::filesystem::path &name, const std::vector< std::string > &args)
Construct a specimen description for a program with arguments.
bool isSet(Enum e) const
Test whether a bit is set.
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(Sawyer::Optional< DetachMode > mode=Sawyer::Nothing())
Detach from the subordinate.
Sawyer::SharedPointer< Debugger > Ptr
Shared-ownership pointer to Debugger.
Sawyer::Container::BitVector readRegister(RegisterDescriptor)
Read subordinate register.
void attach(const Specimen &, Sawyer::Optional< DetachMode > onDelete=Sawyer::Nothing())
Attach to a specimen.
Reference-counting intrusive smart pointer.
Definition: SharedPointer.h:68
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.
bool randomizedAddresses() const
Property: Whether to randomize addresses of a process.
void writeMemory(rose_addr_t va, const T &value)
Write subordinate memory.
const BitFlags< Flag > & flags() const
Property: Operational flags.
Sawyer::Container::Trace< rose_addr_t > trace(Filter &filter)
Run the program and return an execution trace.
void writeRegister(RegisterDescriptor, const Sawyer::Container::BitVector &)
Write subordinate register.
void persona(unsigned long bits)
Property: Personality flags.
int remoteCloseFile(unsigned remoteFd)
Cause the subordinate to close a file.
Describes (part of) a physical CPU register.
static void initDiagnostics()
Initialize diagnostic output.
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.
bool isClear(Enum e) const
Test whether a bit is clear.
void setBreakpoint(const AddressInterval &)
Set breakpoints.
BitFlags< FilterActionFlags > FilterAction
Return value for tracing.
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
FilterActionFlags
Action for trace filter callback.
void eraseAllEnvironmentVariables()
Remove all environment variables.
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.
static Sawyer::Message::Facility mlog
Diagnostic facility for debugger.
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
size_t writeMemory(rose_addr_t va, size_t nBytes, const uint8_t *bytes)
Writes some bytes to subordinate memory.
void clearBreakpoint(const AddressInterval &)
Remove breakpoints.
void eraseEnvironmentVariable(const std::string &)
Remove an environment variable.
std::string howTerminated()
String describing how the subordinate process terminated.
const RegisterDictionary * registerDictionary() const
Available registers.
unsigned long persona() const
Property: Personality flags.
Defines registers available for a particular architecture.
Definition: Registers.h:38
Represents no value.
Definition: Optional.h:32
void insertEnvironmentVariable(const std::string &name, const std::string &value)
Add an environment variable.
Simply detach leaving process in current state.
rose_addr_t remoteMmap(rose_addr_t va, size_t nBytes, unsigned prot, unsigned flags, const boost::filesystem::path &, off_t offset)
Map a new memory region in the subordinate.
bool isTerminated()
Returns true if the subordinate terminated.
Virtual base class for instruction disassemblers.
Definition: Disassembler.h:50
Abort tracing, either appending or rejecting the current address.
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.
Reject the current address, not appending it to the trace.
std::string readCString(rose_addr_t va, size_t maxBytes=UNLIMITED)
Read C-style NUL-terminated string from subordinate.