ROSE  0.9.6a
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
MemoryMap.h
Go to the documentation of this file.
1 #ifndef ROSE_MemoryMap_H
2 #define ROSE_MemoryMap_H
3 
4 #include "ByteOrder.h"
5 #include <boost/shared_ptr.hpp>
6 
7 /* Increase ADDR if necessary to make it a multiple of ALMNT */
8 #define ALIGN_UP(ADDR,ALMNT) ((((ADDR)+(ALMNT)-1)/(ALMNT))*(ALMNT))
9 
10 /* Decrease ADDR if necessary to make it a multiple of ALMNT */
11 #define ALIGN_DN(ADDR,ALMNT) (((ADDR)/(ALMNT))*(ALMNT))
12 
13 
70 class MemoryMap {
71 public:
72 
74  enum Protection {
75  /* Protection bits */
76  MM_PROT_BITS = 0x00000007, /*NO_STRINGIFY*/
77  MM_PROT_READ = 0x00000001,
78  MM_PROT_WRITE = 0x00000002,
79  MM_PROT_EXEC = 0x00000004,
81  /* Protection convenience stuff */
82  MM_PROT_NONE = 0x00000000,
83  MM_PROT_ANY = 0x00000007,
84  MM_PROT_RW = (MM_PROT_READ|MM_PROT_WRITE), /*NO_STRINGIFY*/
85  MM_PROT_RX = (MM_PROT_READ|MM_PROT_EXEC), /*NO_STRINGIFY*/
86  MM_PROT_RWX = (MM_PROT_ANY), /*NO_STRINGIFY*/
87 
88  /* Other flags. These generally aren't interpreted by MemoryMap, but can be used to pass info. When merging memory
89  * segments, MemoryMap::Segment::merge() will not treat two regions as being consistent if they have different
90  * bits set. */
91  MM_PROT_FLAGS = 0xfffffff0,
92  MM_PROT_PRIVATE = 0x00000010,
93  };
94 
96  enum CopyLevel {
100  };
101 
102  /**************************************************************************************************************************
103  * Buffers
104  **************************************************************************************************************************/
105 public:
106  class Buffer;
107  typedef boost::shared_ptr<Buffer> BufferPtr;
108 
113  class Buffer {
114  public:
115  virtual ~Buffer() {}
116 
121  virtual BufferPtr clone() const = 0;
122 
127  virtual bool is_read_only() const { return read_only; }
128  virtual void set_read_only(bool b=true) { read_only = b; }
129  void clear_read_only() { set_read_only(false); } // final
135  virtual std::string get_name() const { return name; }
136  virtual void set_name(const std::string &s) { name = s; }
141  virtual size_t size() const { return p_size; }
142  virtual void resize(size_t n) { p_size = n; }
151  virtual size_t read(void *buf, size_t offset, size_t nbytes) const = 0;
152 
156  virtual size_t write(const void *buf, size_t offset, size_t nbytes) = 0;
157 
160  virtual void save(const std::string &filename) const;
161 
165  virtual const void* get_data_ptr() const = 0;
166 
169  virtual bool is_zero() const;
170 
171  protected:
172  Buffer(size_t size): read_only(false), p_size(size) { name=new_name(); }
173  std::string new_name() /*final*/;
174 
175  bool read_only;
176  std::string name;
177  size_t p_size;
178  };
179 
182  class NullBuffer: public Buffer {
183  public:
185  static BufferPtr create(size_t size);
186 
188  virtual const void *get_data_ptr() const /*overrides*/ { return NULL; }
189 
190  virtual BufferPtr clone() const { return create(size()); }
191  virtual size_t read(void*, size_t offset, size_t nbytes) const /*overrides*/ { return 0; }
192  virtual size_t write(const void*, size_t offset, size_t nbytes) /*overrides*/ { return 0; }
193 
194  protected:
195  NullBuffer(size_t size): Buffer(size) {}
196  };
197 
200  class ExternBuffer: public Buffer {
201  public:
206  static BufferPtr create(void *data, size_t size);
207  static BufferPtr create(const void *data, size_t size);
210  virtual BufferPtr clone() const;
211  virtual void resize(size_t n) /*overrides*/;
212  virtual const void *get_data_ptr() const /*overrides*/ { return p_data; }
213  virtual size_t read(void*, size_t offset, size_t nbytes) const /*overrides*/;
214  virtual size_t write(const void*, size_t offset, size_t nbytes) /*overrides*/;
215 
216  protected:
217  ExternBuffer(const uint8_t *data, size_t size)
218  : Buffer(size), p_data(const_cast<uint8_t*>(data)) { set_read_only(); }
219  ExternBuffer(uint8_t *data, size_t size)
220  : Buffer(size), p_data(data) {}
221  mutable uint8_t *p_data;
222  };
223 
225  class ByteBuffer: public ExternBuffer {
226  public:
227  virtual ~ByteBuffer() { delete[] p_data; }
228 
232  static BufferPtr create(void *data, size_t size);
233 
236  static BufferPtr create_from_file(const std::string &filename, size_t start_offset=0);
237 
238  protected:
239  ByteBuffer(uint8_t *data, size_t size): ExternBuffer(data, size) {}
240  };
241 
243  class MmapBuffer: public ExternBuffer {
244  public:
245  virtual ~MmapBuffer();
246 
250  static BufferPtr create(size_t length, int prot, int flags, int fd, off_t offset);
251 
256  static BufferPtr create(const std::string &filename, int oflags, int mprot, int mflags);
257 
259  virtual void resize(size_t n) /*overrides*/;
260 
261  protected:
262  MmapBuffer(uint8_t *data, size_t size, bool read_only): ExternBuffer(data, size) { set_read_only(read_only); }
263  };
264 
268  public:
269  virtual ~AnonymousBuffer() { delete[] p_data; }
270 
273  static BufferPtr create(size_t size);
274 
275  virtual BufferPtr clone() const /*overrides*/;
276  virtual const void *get_data_ptr() const /*overrides*/;
277  virtual size_t read(void*, size_t offset, size_t nbytes) const /*overrides*/;
278  virtual size_t write(const void*, size_t offset, size_t nbytes) /*overrides*/;
279  virtual bool is_zero() const /*overrides*/;
280 
281  protected:
282  AnonymousBuffer(size_t size): ExternBuffer((uint8_t*)NULL, size) {}
283  };
284 
285  /**************************************************************************************************************************
286  * Segments
287  **************************************************************************************************************************/
288 public:
289 
298  class Segment {
299  public:
301 
304  Segment(const BufferPtr &buffer, rose_addr_t offset, unsigned perms, std::string name="")
305  : buffer(buffer), buffer_offset(offset), mapperms(perms), name(name), copy_on_write(false) {}
306 
313  BufferPtr get_buffer() const { return buffer; }
314  void set_buffer(const BufferPtr &b) { buffer = b; }
326  bool check(const Extent &range, rose_addr_t *first_bad_va=NULL) const;
327 
332  unsigned get_mapperms() const { return mapperms; }
333  void set_mapperms(unsigned p) { mapperms = p; }
349  rose_addr_t get_buffer_offset(const Extent &my_range, rose_addr_t va) const;
357  bool is_cow() const { return copy_on_write; }
358  void set_cow(bool b=true) { copy_on_write = b; }
359  void clear_cow() { set_cow(false); }
364  bool operator==(const Segment &other) const;
365 
368  const std::string &get_name() const { return name; }
369  void set_name(const std::string &s) { name = s; }
372  friend std::ostream& operator<<(std::ostream&, const Segment&);
373 
374  private:
375  // Stuff for manipulating segment debug names
376  typedef std::map<std::string, std::set<std::string> > NamePairings;
377  void merge_names(const Segment &other);
378  std::string get_name_pairings(NamePairings*) const;
379  void set_name(const NamePairings&, const std::string &s1, const std::string &s2);
380 
381  // The following methods are part of the RangeMap interface. See documentation in RangeMap::RangeMapVoid.
382  friend class RangeMap<Extent, Segment>;
383  void removing(const Extent &range);
384  void truncate(const Extent &range, rose_addr_t new_end);
385  bool merge(const Extent &range, const Extent &other_range, const Segment &other_segment);
386  Segment split(const Extent &range, rose_addr_t new_end);
387  void print(std::ostream&) const;
388 
389  private:
390  BufferPtr buffer;
392  unsigned mapperms;
393  std::string name;
395  };
396 
397  /**************************************************************************************************************************
398  * RangeMap-related things
399  **************************************************************************************************************************/
400 public:
406 
407  /**************************************************************************************************************************
408  * Visitors
409  **************************************************************************************************************************/
410 public:
412  class Visitor {
413  public:
414  virtual ~Visitor() {}
415  virtual bool operator()(const MemoryMap*, const Extent&, const Segment&) = 0;
416  };
417 
418  /**************************************************************************************************************************
419  * Exceptions
420  **************************************************************************************************************************/
421 public:
423  class Exception: public std::runtime_error {
424  public:
425  Exception(const std::string &mesg, const MemoryMap *map): std::runtime_error(mesg), map(map) {}
426  virtual ~Exception() throw() {}
427  virtual std::string leader(std::string dflt="memory map problem") const;
428  virtual std::string details(bool) const;
429  virtual void print(std::ostream&, bool verbose=true) const;
430  friend std::ostream& operator<<(std::ostream&, const Exception&);
431  public:
432  const MemoryMap *map;
433  };
434 
439  struct Inconsistent : public Exception {
440  Inconsistent(const std::string &mesg, const MemoryMap *map,
441  const Extent &new_range, const Segment &new_segment,
442  const Extent &old_range, const Segment &old_segment)
443  : Exception(mesg, map),
444  new_range(new_range), old_range(old_range),
445  new_segment(new_segment), old_segment(old_segment) {}
446  virtual ~Inconsistent() throw() {}
447  virtual void print(std::ostream&, bool verbose=true) const;
448  friend std::ostream& operator<<(std::ostream&, const Inconsistent&);
451  };
452 
454  struct NotMapped : public Exception {
455  NotMapped(const std::string &mesg, const MemoryMap *map, rose_addr_t va)
456  : Exception(mesg, map), va(va) {}
457  virtual ~NotMapped() throw() {}
458  virtual void print(std::ostream&, bool verbose=true) const;
459  friend std::ostream& operator<<(std::ostream&, const NotMapped&);
461  };
462 
464  struct NoFreeSpace : public Exception {
465  NoFreeSpace(const std::string &mesg, const MemoryMap *map, size_t size)
466  : Exception(mesg, map), size(size) {}
467  virtual ~NoFreeSpace() throw() {}
468  virtual void print(std::ostream&, bool verbose=true) const;
469  friend std::ostream& operator<<(std::ostream&, const NoFreeSpace&);
470  size_t size;
471  };
472 
474  struct SyntaxError: public Exception {
475  SyntaxError(const std::string &mesg, const MemoryMap *map, const std::string &filename, unsigned linenum, int colnum=-1)
476  : Exception(mesg, map), filename(filename), linenum(linenum), colnum(colnum) {}
477  virtual ~SyntaxError() throw() {}
478  virtual void print(std::ostream&, bool verbose=true) const;
479  friend std::ostream& operator<<(std::ostream&, const SyntaxError&);
480  std::string filename;
481  unsigned linenum;
482  int colnum;
483  };
484 
485  /**************************************************************************************************************************
486  * Public Methods for MemoryMap
487  **************************************************************************************************************************/
488 
490  MemoryMap(): sex(ByteOrder::ORDER_UNSPECIFIED) {}
491 
496  MemoryMap(const MemoryMap &other, CopyLevel copy_level=COPY_SHALLOW)
497  : sex(ByteOrder::ORDER_UNSPECIFIED) {
498  init(other, copy_level);
499  }
500 
504  MemoryMap& init(const MemoryMap &source, CopyLevel copy_level=COPY_SHALLOW);
505 
508  bool empty() const { return p_segments.empty(); }
509 
511  void clear();
512 
514  size_t size() const;
515 
520  void set_byte_order(ByteOrder::Endianness order) { sex = order; }
531  void insert(const Extent &range, const Segment &segment, bool erase_prior=true);
532 
535  size_t insert_file(const std::string &filename, rose_addr_t va, bool writable=false, bool erase_prior=true,
536  const std::string &sgmtname="");
537 
543  bool exists(rose_addr_t va, unsigned required_perms=0) const { return exists(Extent(va), required_perms); }
544  bool exists(Extent range, unsigned required_perms=0) const;
553  void erase(const Extent &range);
554 
557  void erase(const Segment&);
558 
562  std::pair<Extent, Segment> at(rose_addr_t va) const;
563 
567  rose_addr_t find_free(rose_addr_t start_va, size_t size, rose_addr_t mem_alignment=1) const;
568 
573 
575  void traverse(Visitor &visitor) const;
576 
580  void prune(Visitor &predicate);
581 
584  void prune(unsigned required, unsigned prohibited=MM_PROT_NONE);
585 
587  void erase_zeros(size_t minsize);
588 
590  const Segments &segments() const { return p_segments; }
591 
605  size_t read(void *dst_buf, rose_addr_t start_va, size_t desired, unsigned req_perms=MM_PROT_READ) const;
606  size_t read1(void *dst_buf, rose_addr_t start_va, size_t desired, unsigned req_perms=MM_PROT_READ) const;
613  SgUnsignedCharList read(rose_addr_t start_va, size_t desired, unsigned req_perms=MM_PROT_READ) const;
614 
626  std::string read_string(rose_addr_t start_va, size_t desired, int(*valid_char)(int)=NULL, int(*invalid_char)(int)=NULL,
627  unsigned req_perms=MM_PROT_READ) const;
628 
640  size_t write(const void *src_buf, rose_addr_t start_va, size_t desired, unsigned req_perms=MM_PROT_WRITE);
641  size_t write1(const void *src_buf, rose_addr_t start_va, size_t desired, unsigned req_perms=MM_PROT_WRITE);
645  ExtentMap va_extents() const;
646 
650  void mprotect(Extent range, unsigned perms, bool relax=false);
651 
655  void dump(FILE*, const char *prefix="") const;
656  void dump(std::ostream&, std::string prefix="") const;
657  void print(std::ostream &o, std::string prefix="") const { dump(o, prefix); }
663  void dump(const std::string &basename) const;
664 
687  bool load(const std::string &basename);
688 
689  friend std::ostream& operator<<(std::ostream&, const MemoryMap&);
690 
691  /**************************************************************************************************************************
692  * Data members
693  **************************************************************************************************************************/
694 protected:
695  Segments p_segments;
697 };
698 
699 #endif