ROSE  0.11.109.0
LinuxI386.h
1 #ifndef ROSE_BinaryAnalysis_Concolic_LinuxI386_H
2 #define ROSE_BinaryAnalysis_Concolic_LinuxI386_H
3 #include <featureTests.h>
4 #ifdef ROSE_ENABLE_CONCOLIC_TESTING
5 
6 #include <Rose/BinaryAnalysis/Concolic/Architecture.h>
7 #include <Rose/BinaryAnalysis/Concolic/ExecutionEvent.h>
8 #include <Rose/BinaryAnalysis/Concolic/SharedMemory.h>
9 #include <Rose/BinaryAnalysis/Concolic/SystemCall.h>
10 #include <Rose/BinaryAnalysis/Debugger/Linux.h>
11 
12 #include <boost/filesystem.hpp>
13 #include <Sawyer/Callbacks.h>
14 
15 namespace Rose {
16 namespace BinaryAnalysis {
17 namespace Concolic {
18 
20 // Linux Intel 80386 and compatible hardware architecture.
22 
24 class LinuxI386: public Architecture {
25  using Super = Architecture;
26 
27 public:
29  using Ptr = LinuxI386Ptr;
30 
31 private:
32  Debugger::Linux::Ptr debugger_;
33  rose_addr_t scratchVa_ = 0; // subordinate address for scratch page
34  bool markingArgvAsInput_ = true;
35  bool markingEnvpAsInput_ = false;
36 
37 protected:
38  LinuxI386(const DatabasePtr&, TestCaseId, const Partitioner2::Partitioner&);
39 public:
40  ~LinuxI386();
41 
42 public:
48  static Ptr instance(const DatabasePtr&, TestCaseId, const Partitioner2::Partitioner&);
49  static Ptr instance(const DatabasePtr&, const TestCasePtr&, const Partitioner2::Partitioner&);
55  Debugger::Linux::Ptr debugger() const;
56 
57 public:
59  RegisterDescriptor systemCallReturnRegister();
60 
61 public:
62  // These are documented in the base class.
63  virtual void configureSystemCalls() override;
64  virtual void configureSharedMemory() override;
65  virtual void load(const boost::filesystem::path&) override;
66  virtual bool isTerminated() override;
67  virtual ByteOrder::Endianness memoryByteOrder() override;
68  virtual std::string readCString(rose_addr_t va, size_t maxBytes = UNLIMITED) override;
69  virtual rose_addr_t ip() override;
70  virtual void ip(rose_addr_t) override;
71  virtual std::vector<ExecutionEventPtr> createMemoryRestoreEvents() override;
72  virtual std::vector<ExecutionEventPtr> createMemoryHashEvents() override;
73  virtual std::vector<ExecutionEventPtr> createMemoryAdjustEvents(const MemoryMap::Ptr&, rose_addr_t insnVa) override;
74  virtual std::vector<ExecutionEventPtr> createRegisterRestoreEvents() override;
75  virtual bool playEvent(const ExecutionEventPtr&) override;
76  virtual void mapMemory(const AddressInterval&, unsigned permissions) override;
77  virtual void unmapMemory(const AddressInterval&) override;
78  virtual size_t writeMemory(rose_addr_t, const std::vector<uint8_t>&) override;
79  virtual std::vector<uint8_t> readMemory(rose_addr_t, size_t) override;
80  virtual void writeRegister(RegisterDescriptor, uint64_t) override;
81  virtual void writeRegister(RegisterDescriptor, const Sawyer::Container::BitVector&) override;
82  virtual Sawyer::Container::BitVector readRegister(RegisterDescriptor) override;
83  virtual void executeInstruction(const Partitioner2::Partitioner&) override;
84  virtual void executeInstruction(const InstructionSemantics::BaseSemantics::RiscOperatorsPtr&, SgAsmInstruction*) override;
85  virtual void createInputVariables(const Partitioner2::Partitioner&, const Emulation::RiscOperatorsPtr&,
86  const SmtSolver::Ptr &solver) override;
87  virtual void systemCall(const Partitioner2::Partitioner&,
89 
90 private:
91  // Maps a scratch page for internal use and updates scratchVa_ with the address of the page.
92  void mapScratchPage();
93 
94  // Copy (share) some data from the dst map to the src map at where. Generate map and write events that will map the memory
95  // and initialize it when played back.
96  std::vector<ExecutionEventPtr> copyMemory(const MemoryMap::Ptr &src, const MemoryMap::Ptr &dst, const AddressInterval &where,
97  rose_addr_t insnVa);
98 
99  // List of process memory segments that are not special.
100  std::vector<MemoryMap::ProcessMapRecord> disposableMemory();
101 
102  // Unmap nearly all memory. The scratch page is not unmapped, nor is the VDSO or VVAR.
103  void unmapAllMemory();
104 
105  // When stopped at the beginning of a system call, return the system call function number. See <sys/unistd_32.h> for the
106  // mapping function system call number to the Linux kernel function that handles it.
107  uint64_t systemCallFunctionNumber(const Partitioner2::Partitioner&,
109 
110  // Returns the system call argument.
112  systemCallArgument(const Partitioner2::Partitioner&,
114 
115  // Returns the system call return value.
117  systemCallReturnValue(const Partitioner2::Partitioner&,
119 
120  // Modify the symbolic system call return value.
122  systemCallReturnValue(const Partitioner2::Partitioner&,
125 
126 };
127 
129 // Linux i386 specific system call operations.
131 
135 class LinuxI386SyscallBase: public SyscallCallback {
136  ExecutionEventPtr latestReturnEvent_; // event for most recent system call return
137  ExecutionEventPtr penultimateReturnEvent_; // event for next most recent system call return
138 
139 public:
140  LinuxI386SyscallBase();
141  virtual ~LinuxI386SyscallBase();
142 
148  void hello(const std::string &name, const SyscallContext&) const;
149 
155  virtual void playback(SyscallContext&) = 0;
156 
174  virtual void handlePreSyscall(SyscallContext&) {}
175  virtual void handlePostSyscall(SyscallContext&) = 0;
192  ExecutionEventPtr latestReturnEvent() const;
193  ExecutionEventPtr penultimateReturnEvent() const;
200  void showRecentReturnValues(std::ostream&, const SyscallContext&) const;
201 
207  SymbolicExpressionPtr penultimateSymbolicReturn() const;
208 
209 public:
210  // Subclasses need not provide a function operator.
211  virtual bool operator()(bool /*handled*/, SyscallContext&) override final;
212 };
213 
219 class LinuxI386SyscallUnimplemented: public LinuxI386SyscallBase {
220 protected:
221  LinuxI386SyscallUnimplemented();
222 public:
223  ~LinuxI386SyscallUnimplemented();
224 
225 public:
227  static Ptr instance();
228 
229  void playback(SyscallContext&) override;
230  void handlePostSyscall(SyscallContext&) override;
231 };
232 
237 class LinuxI386SyscallReturnsInput: public LinuxI386SyscallBase {
238 protected:
239  LinuxI386SyscallReturnsInput();
240 public:
241  ~LinuxI386SyscallReturnsInput();
242 
243 public:
245  static Ptr instance();
246 
247  void playback(SyscallContext&) override;
248  void handlePostSyscall(SyscallContext&) override;
249 };
250 
252 class LinuxI386SyscallTerminates: public LinuxI386SyscallBase {
253 protected:
254  LinuxI386SyscallTerminates();
255 public:
256  ~LinuxI386SyscallTerminates();
257 
258 public:
260  static Ptr instance();
261 
262  void playback(SyscallContext&) override;
263  void handlePostSyscall(SyscallContext&) override;
264 };
265 
269 class LinuxI386SyscallReturn: public LinuxI386SyscallBase {
270 protected:
271  LinuxI386SyscallReturn();
272 public:
273  ~LinuxI386SyscallReturn();
274 
275 protected:
282  virtual std::pair<SymbolicExpressionPtr, Sawyer::Optional<uint64_t>> makeReturnConstraint(SyscallContext&) = 0;
283 
284 public:
285  void handlePostSyscall(SyscallContext&) override final;
286 };
287 
293 class LinuxI386SyscallConstant: public LinuxI386SyscallReturn {
294 protected:
295  LinuxI386SyscallConstant();
296 public:
297  ~LinuxI386SyscallConstant();
298 
299 public:
301  static Ptr instance();
302 
303  void playback(SyscallContext&) override;
304  std::pair<SymbolicExpressionPtr, Sawyer::Optional<uint64_t>> makeReturnConstraint(SyscallContext&) override;
305 };
306 
310 class LinuxI386SyscallNondecreasing: public LinuxI386SyscallReturn {
311 protected:
312  LinuxI386SyscallNondecreasing();
313 public:
314  ~LinuxI386SyscallNondecreasing();
315 
316 public:
318  static Ptr instance();
319 
320  void playback(SyscallContext&) override;
321  std::pair<SymbolicExpressionPtr, Sawyer::Optional<uint64_t>> makeReturnConstraint(SyscallContext&) override;
322 };
323 
325 class LinuxI386SyscallAccess: public LinuxI386SyscallBase {
326 protected:
327  LinuxI386SyscallAccess();
328 public:
329  ~LinuxI386SyscallAccess();
330 
331 public:
333  static Ptr instance();
334 
335  void playback(SyscallContext&) override;
336  void handlePostSyscall(SyscallContext&) override;
337 };
338 
340 class LinuxI386SyscallBrk: public LinuxI386SyscallBase {
341 protected:
342  LinuxI386SyscallBrk();
343 public:
344  ~LinuxI386SyscallBrk();
345 
346 public:
348  static Ptr instance();
349 
350  void playback(SyscallContext&) override;
351  void handlePostSyscall(SyscallContext&) override;
352 };
353 
355 class LinuxI386SyscallMmap2: public LinuxI386SyscallBase {
356 protected:
357  LinuxI386SyscallMmap2();
358 public:
359  ~LinuxI386SyscallMmap2();
360 
361 public:
363  static Ptr instance();
364 
365  void playback(SyscallContext&) override;
366  void handlePostSyscall(SyscallContext&) override;
367 };
368 
370 class LinuxI386SyscallOpenat: public LinuxI386SyscallBase {
371 protected:
372  LinuxI386SyscallOpenat();
373 public:
374  ~LinuxI386SyscallOpenat();
375 
376 public:
378  static Ptr instance();
379 
380  void playback(SyscallContext&) override;
381  void handlePostSyscall(SyscallContext&) override;
382 };
383 
384 } // namespace
385 } // namespace
386 } // namespace
387 
388 #endif
389 #endif
SmtSolverPtr Ptr
Reference counting pointer for SMT solvers.
Definition: SmtSolver.h:45
boost::shared_ptr< RiscOperators > RiscOperatorsPtr
Shared-ownership pointer to a RISC operators object.
Base class for machine instructions.
Main namespace for the ROSE library.
const size_t UNLIMITED(static_cast< size_t >(-1))
Effictively unlimited size.
MemoryMapPtr Ptr
Reference counting pointer.
Definition: MemoryMap.h:115
ROSE_DLL_API void load(SgProject *project, std::list< std::string > const &filepaths)
Load ASTs that have been saved to files.
const char * Architecture(int64_t)
Convert Rose::BinaryAnalysis::Disassembler::Mips::Decoder::Architecture enum constant to a string...
Sawyer::SharedPointer< SValue > SValuePtr
Shared-ownership pointer to a semantic value in any domain.
Sawyer::SharedPointer< Node > Ptr
Reference counting pointer.