ROSE  0.11.145.0
MemoryMap.h
1 #ifndef ROSE_BinaryAnalysis_MemoryMap_H
2 #define ROSE_BinaryAnalysis_MemoryMap_H
3 #include <featureTests.h>
4 #ifdef ROSE_ENABLE_BINARY_ANALYSIS
5 
6 #include <Rose/BinaryAnalysis/BasicTypes.h>
7 #include <Rose/BinaryAnalysis/ByteOrder.h>
8 
9 #include <Combinatorics.h>
10 #include <Rose/Exception.h>
11 
12 #include <Sawyer/Access.h>
13 #include <Sawyer/AddressMap.h>
14 #include <Sawyer/AllocatingBuffer.h>
15 #include <Sawyer/MappedBuffer.h>
16 #include <Sawyer/NullBuffer.h>
17 #include <Sawyer/Optional.h>
18 #include <Sawyer/StaticBuffer.h>
19 
20 #include <boost/config.hpp>
21 #include <boost/utility/enable_if.hpp>
22 #include <boost/serialization/access.hpp>
23 #include <boost/serialization/base_object.hpp>
24 #include <boost/serialization/export.hpp>
25 #include <boost/type_traits/is_integral.hpp>
26 
27 namespace Rose {
28 namespace BinaryAnalysis {
29 
35 template<typename T, typename U>
36 typename boost::enable_if_c<boost::is_integral<T>::value && boost::is_integral<U>::value, T>::type
37 alignUp(T address, U alignment) {
38  ASSERT_require(alignment > 0);
39  T almt = static_cast<T>(alignment);
40  return ((address + almt - 1) / almt) * almt;
41 }
42 
48 template<typename T, typename U>
49 typename boost::enable_if_c<boost::is_integral<T>::value && boost::is_integral<U>::value, T>::type
50 alignDown(T address, U alignment) {
51  ASSERT_require(alignment > 0);
52  T almt = static_cast<T>(alignment);
53  return (address / almt) * almt;
54 }
55 
112 class MemoryMap: public Sawyer::Container::AddressMap<rose_addr_t, uint8_t>, public Sawyer::SharedObject {
113 public:
115  using Ptr = MemoryMapPtr;
116 
117  typedef rose_addr_t Address;
118  typedef uint8_t Value;
128 
130  struct Attach { // For consistency with other <Feature>::Boolean types
131  enum Boolean {
132  NO,
134  };
135  };
136 
138  enum class Clobber {NO, YES};
139 
140 private:
141  ByteOrder::Endianness endianness_;
142 
143 #ifdef ROSE_HAVE_BOOST_SERIALIZATION_LIB
144 private:
145  friend class boost::serialization::access;
146 
147  template<class S>
148  void serialize(S &s, const unsigned /*version*/) {
149  s.template register_type<AllocatingBuffer>();
150  s.template register_type<MappedBuffer>();
151  s.template register_type<NullBuffer>();
152  s.template register_type<StaticBuffer>();
153  s & BOOST_SERIALIZATION_BASE_OBJECT_NVP(Super);
154  s & BOOST_SERIALIZATION_NVP(endianness_);
155  }
156 #endif
157 
158 public:
159 
160  // Whoever pollutes all namespaces with these common word preprocessor symbols is a lunatic!
161 # if defined(READABLE) || defined(WRITABLE) || defined(EXECUTABLE) || defined(IMMUTABLE) || defined(PRIVATE)
162 # ifdef _MSC_VER
163 # pragma message("Undefining common words from the global namespace: READABLE, WRITABLE, EXECUTABLE, IMMUTABLE, PRIVATE")
164 # else
165 # warning "Undefining common words from the global namespace: READABLE, WRITABLE, EXECUTABLE, IMMUTABLE, PRIVATE"
166 # endif
167 # undef READABLE
168 # undef WRITABLE
169 # undef EXECUTABLE
170 # undef IMMUTABLE
171 # undef PRIVATE
172 # endif
173 
174  // Accessibility flags
175  static const unsigned NO_ACCESS = 0;
176  static const unsigned READABLE = Sawyer::Access::READABLE;
177  static const unsigned WRITABLE = Sawyer::Access::WRITABLE;
178  static const unsigned EXECUTABLE = Sawyer::Access::EXECUTABLE;
179  static const unsigned IMMUTABLE = Sawyer::Access::IMMUTABLE;
180  static const unsigned PRIVATE = Sawyer::Access::PRIVATE;
181  static const unsigned INITIALIZED = 0x00000200; // Partitioner2: initialized memory even if writable
182 
183  // Aggregate accessibility flags
184  static const unsigned READ_WRITE = READABLE | WRITABLE;
185  static const unsigned READ_EXECUTE = READABLE | EXECUTABLE;
186  static const unsigned READ_WRITE_EXECUTE = READABLE | WRITABLE | EXECUTABLE;
187 
188  // These bits are reserved for use in ROSE
189  static const unsigned RESERVED_ACCESS_BITS = 0x0000ffff;
190 
191 
192 public:
194  class Exception: public Rose::Exception {
195  public:
196  Exception(const std::string &mesg, const MemoryMap::Ptr map): Rose::Exception(mesg), map(map) {}
197  virtual ~Exception() throw() {}
198  virtual std::string leader(std::string dflt="memory map problem") const;
199  virtual std::string details(bool) const;
200  virtual void print(std::ostream&, bool verbose=true) const;
201  friend std::ostream& operator<<(std::ostream&, const Exception&);
202  public:
204  };
205 
210  struct Inconsistent : public Exception {
211  Inconsistent(const std::string &mesg, const MemoryMap::Ptr &map,
212  const AddressInterval &new_range, const Segment &new_segment,
213  const AddressInterval &old_range, const Segment &old_segment)
214  : Exception(mesg, map),
215  new_range(new_range), old_range(old_range),
216  new_segment(new_segment), old_segment(old_segment) {}
217  virtual ~Inconsistent() throw() {}
218  virtual void print(std::ostream&, bool verbose=true) const;
219  friend std::ostream& operator<<(std::ostream&, const Inconsistent&);
220  AddressInterval new_range, old_range;
221  Segment new_segment, old_segment;
222  };
223 
225  struct NotMapped : public Exception {
226  NotMapped(const std::string &mesg, const MemoryMap::Ptr &map, rose_addr_t va)
227  : Exception(mesg, map), va(va) {}
228  virtual ~NotMapped() throw() {}
229  virtual void print(std::ostream&, bool verbose=true) const;
230  friend std::ostream& operator<<(std::ostream&, const NotMapped&);
231  rose_addr_t va;
232  };
233 
235  struct NoFreeSpace : public Exception {
236  NoFreeSpace(const std::string &mesg, const MemoryMap::Ptr &map, size_t size)
237  : Exception(mesg, map), size(size) {}
238  virtual ~NoFreeSpace() throw() {}
239  virtual void print(std::ostream&, bool verbose=true) const;
240  friend std::ostream& operator<<(std::ostream&, const NoFreeSpace&);
241  size_t size;
242  };
243 
245  struct SyntaxError: public Exception {
246  SyntaxError(const std::string &mesg, const MemoryMap::Ptr &map, const std::string &filename,
247  unsigned linenum, int colnum=-1)
248  : Exception(mesg, map), filename(filename), linenum(linenum), colnum(colnum) {}
249  virtual ~SyntaxError() throw() {}
250  virtual void print(std::ostream&, bool verbose=true) const;
251  friend std::ostream& operator<<(std::ostream&, const SyntaxError&);
252  std::string filename;
253  unsigned linenum;
254  int colnum;
255  };
256 
257 protected:
259  MemoryMap(): endianness_(ByteOrder::ORDER_UNSPECIFIED) {}
260 
261 public:
263  static Ptr instance() {
264  return Ptr(new MemoryMap);
265  }
266 
271  return Ptr(new MemoryMap(*this));
272  }
273 
281  ByteOrder::Endianness byteOrder() const { return endianness_; }
282  void byteOrder(ByteOrder::Endianness order) { endianness_ = order; }
285  // Note that the order of the enum members is for backward compatibility with an older version of insertFile whose third
286  // argument was "bool writable = false" (MAP_RDONLY, but now intended to be MAP_PRIVATE) and when it was true was the same
287  // as MAP_READWRITE.
288  //
297  };
298 
303  size_t insertFile(const std::string &fileName, rose_addr_t va, InsertFileMapMode mode = MAP_PRIVATE,
304  std::string segmentName = "");
305 
381  AddressInterval insertFile(const std::string &locatorString);
382 
384  static std::string insertFileDocumentation();
385 
412  AddressInterval insertData(const std::string &locatorString);
413 
415  static std::string insertDataDocumentation();
416 
421  void adjustMap(const std::string &locatorString);
422 
424  static std::string adjustMapDocumentation();
425 
426 
429  AddressInterval interval;
430  unsigned accessibility;
431  rose_addr_t fileOffset;
432  std::string deviceName;
433  size_t inode;
434  std::string comment;
437  : accessibility(0), fileOffset(0), inode(0) {}
438  };
439 
443  static std::vector<ProcessMapRecord> readProcessMap(pid_t);
444 
445 #ifdef BOOST_WINDOWS
446  void insertProcess(int pid, Attach::Boolean attach);
447 #else
448 
449  void insertProcess(pid_t pid, Attach::Boolean attach);
450 #endif
451 
455  void insertProcess(const std::string &locatorString);
456 
460  bool insertProcessPid(pid_t, const AddressInterval &where, unsigned accessibility, const std::string &name);
461  void insertProcessPid(pid_t, const std::vector<ProcessMapRecord>&);
462  bool insertProcessMemory(int memFile, const AddressInterval &where, unsigned accessibility, std::string name);
466  static std::string insertProcessDocumentation();
467 
481  AddressIntervalSet linkTo(const MemoryMap::Ptr &source, const AddressIntervalSet &where, Clobber = Clobber::YES);
482  AddressIntervalSet linkTo(const MemoryMap::Ptr &source, const AddressInterval &where, Clobber = Clobber::YES);
495  MemoryMap::Ptr align(rose_addr_t lowAlignment, rose_addr_t highAlignment) const;
496 
502  static std::pair<Buffer::Ptr, std::string> copyFromFile(int fd, const AddressInterval&);
503 
505  void eraseZeros(size_t minsize);
506 
517  bool shrinkUnshare();
518 
520  size_t readQuick(void *buf, rose_addr_t startVa, size_t desired) const {
521  return at(startVa).limit(desired).require(READABLE).read((uint8_t*)buf).size();
522  }
523 
536  std::string readString(rose_addr_t startVa, size_t desired, int(*validChar)(int)=NULL, int(*invalidChar)(int)=NULL,
537  unsigned requiredPerms=READABLE, unsigned prohibitedPerms=0, char terminator='\0') const;
538 
544  template<typename U>
545  Sawyer::Optional<U> readUnsigned(rose_addr_t startVa) const {
546  U val = 0;
547  if (at(startVa).limit(sizeof val).read((uint8_t*)&val).size() != sizeof val)
548  return Sawyer::Nothing();
549  ByteOrder::convert((void*)&val, sizeof val, endianness_, ByteOrder::hostOrder());
550  return val;
551  }
552 
558  Sawyer::Optional<uint64_t> readLongUnsinged(rose_addr_t startVa) const {
559  uint64_t val = 0;
560  if (at(startVa).limit(sizeof val).read((uint8_t*)&val).size() != sizeof val)
561  return Sawyer::Nothing();
562  ByteOrder::convert((void*)&val, sizeof val, endianness_, ByteOrder::hostOrder());
563  return val;
564  }
565 
570  size_t writeUnsigned(uint32_t value, rose_addr_t startVa) {
571  return at(startVa).limit(sizeof(uint32_t)).write((const uint8_t*)(&value)).size();
572  }
573 
578  size_t writeUnsigned(uint64_t value, rose_addr_t startVa) {
579  return at(startVa).limit(sizeof(uint64_t)).write((const uint8_t*)(&value)).size();
580  }
581 
585  Sawyer::Optional<uint8_t> readByte(rose_addr_t) const;
586 
588  SgUnsignedCharList readVector(rose_addr_t startVa, size_t desired, unsigned requiredPerms=READABLE) const;
589 
591  size_t writeQuick(const void *buf, rose_addr_t startVa, size_t desired) {
592  return at(startVa).limit(desired).require(WRITABLE).write((const uint8_t*)buf).size();
593  }
594 
602  Sawyer::Optional<rose_addr_t> findAny(const Extent &limits, const std::vector<uint8_t> &bytesToFind,
603  unsigned requiredPerms=READABLE, unsigned prohibitedPerms=0) const;
604  Sawyer::Optional<rose_addr_t> findAny(const AddressInterval &limits, const std::vector<uint8_t> &bytesToFind,
605  unsigned requiredPerms=READABLE, unsigned prohibitedPerms=0) const;
613  Sawyer::Optional<rose_addr_t> findSequence(const AddressInterval &interval, const std::vector<uint8_t> &sequence) const;
614 
618  void dump(FILE*, const char *prefix="") const;
619  void dump(std::ostream&, std::string prefix="") const;
620  void print(std::ostream &o, std::string prefix="") const { dump(o, prefix); }
621  void dump() const; // mostly for calling from within GDB or similar
639 
641  static std::string segmentTitle(const Segment&);
642 
643  friend std::ostream& operator<<(std::ostream&, const MemoryMap&);
644 };
645 
646 } // namespace
647 } // namespace
648 
649 // Register the types needed for serialization since some of them are derived from polymorphic class templates.
650 #ifdef ROSE_HAVE_BOOST_SERIALIZATION_LIB
652 BOOST_CLASS_EXPORT_KEY(Rose::BinaryAnalysis::MemoryMap::MappedBuffer);
653 BOOST_CLASS_EXPORT_KEY(Rose::BinaryAnalysis::MemoryMap::NullBuffer);
654 BOOST_CLASS_EXPORT_KEY(Rose::BinaryAnalysis::MemoryMap::StaticBuffer);
655 #endif
656 
657 #endif
658 #endif
Exception thrown by find_free() when there's not enough free space left.
Definition: MemoryMap.h:235
int colnum
Optional column number (0-origin; negative if unknown).
Definition: MemoryMap.h:254
Sawyer::Optional< uint8_t > readByte(rose_addr_t) const
Read a byte from memory.
Sawyer::Optional< uint64_t > readLongUnsinged(rose_addr_t startVa) const
Read a long unsigned value.
Definition: MemoryMap.h:558
Points to static data.
Definition: StaticBuffer.h:30
static std::string adjustMapDocumentation()
Documentation string for adjustMap.
Exception thrown by load() when there's a syntax error in the index file.
Definition: MemoryMap.h:245
virtual std::string leader(std::string dflt="memory map problem") const
Leading part of the error message.
static std::pair< Buffer::Ptr, std::string > copyFromFile(int fd, const AddressInterval &)
Copy part of a file into a buffer.
void print(std::ostream &o, std::string prefix="") const
Prints the contents of the map for debugging.
Definition: MemoryMap.h:620
virtual std::string details(bool) const
Details emitted on following lines, indented two spaces.
AddressMapConstraints< const AddressMap > at(Address x) const
Constraint: anchor point.
Definition: AddressMap.h:1114
static std::string insertFileDocumentation()
Documentation string for insertFile.
size_t insertFile(const std::string &fileName, rose_addr_t va, InsertFileMapMode mode=MAP_PRIVATE, std::string segmentName="")
Insert file contents into memory map.
A contiguous range of values.
Definition: rangemap.h:50
InsertFileMapMode
Mapping mode for insertFile.
Definition: MemoryMap.h:290
rose_addr_t fileOffset
The accessibility flags.
Definition: MemoryMap.h:431
MemoryMap()
Constructs an empty memory map.
Definition: MemoryMap.h:259
Holds a value or nothing.
Definition: Optional.h:49
MemoryMap::Ptr map
Map that caused the exception if available, null otherwise.
Definition: MemoryMap.h:203
Attach with ptrace, get memory, then detach.
Definition: MemoryMap.h:133
AddressSegment< rose_addr_t, uint8_t > Segment
Type of segments stored by this map.
Definition: AddressMap.h:1010
AddressInterval insertData(const std::string &locatorString)
Insert data into a memory map.
Main namespace for the ROSE library.
Information about a process map.
Definition: MemoryMap.h:428
Memory mapped file.
Definition: MappedBuffer.h:43
File is mapped with read-only permission.
Definition: MemoryMap.h:295
Sawyer::SharedPointer< MemoryMap > MemoryMapPtr
Reference counting pointer.
Allocates memory as needed.
std::string filename
Name of index file where error occurred.
Definition: MemoryMap.h:252
Combinatorics::Hasher & hash(Combinatorics::Hasher &) const
Compute a hash of the entire memory contents.
MemoryMapPtr Ptr
Reference counting pointer.
Definition: MemoryMap.h:115
static Ptr instance()
Construct an empty memory map.
Definition: MemoryMap.h:263
void byteOrder(ByteOrder::Endianness order)
Property: byte order.
Definition: MemoryMap.h:282
Sawyer::Container::Interval< Address > read(Value *buf, const AddressMapConstraints< const AddressMap > &c, MatchFlags flags=0) const
Reads data into the supplied buffer.
Definition: AddressMap.h:1691
File is mapped with read and write permission.
Definition: MemoryMap.h:293
size_t readQuick(void *buf, rose_addr_t startVa, size_t desired) const
Read data into buffer.
Definition: MemoryMap.h:520
void insertProcess(pid_t pid, Attach::Boolean attach)
Insert the memory of some other process into this memory map.
size_t inode
The device from which the data is mapped, or "00:00".
Definition: MemoryMap.h:433
Exception for when we try to access a virtual address that isn't mapped.
Definition: MemoryMap.h:225
A mapping from address space to values.
Definition: AddressMap.h:1003
unsigned accessibility
Mapped virtual addresses.
Definition: MemoryMap.h:430
Buffer that has no data.
Definition: NullBuffer.h:26
Base class for all buffers.
Definition: Buffer.h:25
An efficient mapping from an address space to stored data.
Definition: MemoryMap.h:112
MemoryMap::Ptr align(rose_addr_t lowAlignment, rose_addr_t highAlignment) const
Create a new map by padding and aligning segments.
size_t writeUnsigned(uint32_t value, rose_addr_t startVa)
Write an unsigned value.
Definition: MemoryMap.h:570
bool insertProcessMemory(int memFile, const AddressInterval &where, unsigned accessibility, std::string name)
Insert part of another process's memory into this memory map.
boost::enable_if_c< boost::is_integral< T >::value &&boost::is_integral< U >::value, T >::type alignDown(T address, U alignment)
Align address upward to boundary.
Definition: MemoryMap.h:50
boost::enable_if_c< boost::is_integral< T >::value &&boost::is_integral< U >::value, T >::type alignUp(T address, U alignment)
Align address downward to boundary.
Definition: MemoryMap.h:37
unsigned linenum
Line number (1 origin) where error occurred.
Definition: MemoryMap.h:253
Constraints are used to select addresses from a memory map.
Definition: AddressMap.h:79
Sawyer::Optional< rose_addr_t > findSequence(const AddressInterval &interval, const std::vector< uint8_t > &sequence) const
Search for a byte sequence.
void adjustMap(const std::string &locatorString)
Adjusts a memory map according to the locator string.
static std::vector< ProcessMapRecord > readProcessMap(pid_t)
Obtain the memory map information for a process.
std::string readString(rose_addr_t startVa, size_t desired, int(*validChar)(int)=NULL, int(*invalidChar)(int)=NULL, unsigned requiredPerms=READABLE, unsigned prohibitedPerms=0, char terminator='\0') const
Reads a NUL-terminated string from the memory map.
Base class for reference counted objects.
Definition: SharedObject.h:64
Exception for an inconsistent mapping.
Definition: MemoryMap.h:210
std::string deviceName
Starting byte offset in the file.
Definition: MemoryMap.h:432
size_t writeUnsigned(uint64_t value, rose_addr_t startVa)
Write a long unsigned value.
Definition: MemoryMap.h:578
void eraseZeros(size_t minsize)
Erases regions of zero bytes that are executable and readable and at least minsize in size...
bool insertProcessPid(pid_t, const AddressInterval &where, unsigned accessibility, const std::string &name)
Insert part of another process's memory into this memory map.
SgUnsignedCharList readVector(rose_addr_t startVa, size_t desired, unsigned requiredPerms=READABLE) const
Read quickly into a vector.
Attach with ptrace first when reading a process?
Definition: MemoryMap.h:130
std::string comment
Inode on the device, or zero.
Definition: MemoryMap.h:434
bool shrinkUnshare()
Shrink buffers and remove sharing.
Represents no value.
Definition: Optional.h:32
Clobber
Overwrite (parts of) existing segments?
Definition: MemoryMap.h:138
AddressIntervalSet linkTo(const MemoryMap::Ptr &source, const AddressIntervalSet &where, Clobber=Clobber::YES)
Insert part of another map by reference.
ByteOrder::Endianness byteOrder() const
Property: byte order.
Definition: MemoryMap.h:281
void dump() const
Prints the contents of the map for debugging.
static std::string insertDataDocumentation()
Documentation string for insertData.
Sawyer::Optional< rose_addr_t > findAny(const Extent &limits, const std::vector< uint8_t > &bytesToFind, unsigned requiredPerms=READABLE, unsigned prohibitedPerms=0) const
Search for any byte.
static std::string segmentTitle(const Segment &)
Title of a segment when printing the map.
Base class for all ROSE exceptions.
Definition: Rose/Exception.h:9
static std::string insertProcessDocumentation()
Documentation string for insertProcess.
AddressMapConstraints< const AddressMap > limit(size_t x) const
Constraint: limit matched size.
Definition: AddressMap.h:1155
size_t writeQuick(const void *buf, rose_addr_t startVa, size_t desired)
Write data from buffer.
Definition: MemoryMap.h:591
Sawyer::Optional< U > readUnsigned(rose_addr_t startVa) const
Read an unsigned value.
Definition: MemoryMap.h:545
Exception for MemoryMap operations.
Definition: MemoryMap.h:194
Assume ptrace is attached and process is stopped.
Definition: MemoryMap.h:132
Ptr shallowCopy()
Create a new copy of the memory map.
Definition: MemoryMap.h:270