ROSE 0.11.145.250
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/AddressIntervalSet.h>
7#include <Rose/BinaryAnalysis/BasicTypes.h>
8#include <Rose/BinaryAnalysis/ByteOrder.h>
9#include <Rose/Exception.h>
10
11#include <Combinatorics.h>
12#include <rose_extent.h>
13#include <sageContainer.h>
14
15#include <Sawyer/Access.h>
16#include <Sawyer/AddressMap.h>
17#include <Sawyer/AllocatingBuffer.h>
18#include <Sawyer/MappedBuffer.h>
19#include <Sawyer/NullBuffer.h>
20#include <Sawyer/Optional.h>
21#include <Sawyer/StaticBuffer.h>
22
23#include <boost/config.hpp>
24#include <boost/utility/enable_if.hpp>
25#include <boost/type_traits/is_integral.hpp>
26
27#ifdef ROSE_ENABLE_BOOST_SERIALIZATION
28#include <boost/serialization/access.hpp>
29#include <boost/serialization/base_object.hpp>
30#include <boost/serialization/export.hpp>
31#endif
32
33
34namespace Rose {
35namespace BinaryAnalysis {
36
42template<typename T, typename U>
43typename boost::enable_if_c<boost::is_integral<T>::value && boost::is_integral<U>::value, T>::type
44alignUp(T address, U alignment) {
45 ASSERT_require(alignment > 0);
46 T almt = static_cast<T>(alignment);
47 return ((address + almt - 1) / almt) * almt;
48}
49
55template<typename T, typename U>
56typename boost::enable_if_c<boost::is_integral<T>::value && boost::is_integral<U>::value, T>::type
57alignDown(T address, U alignment) {
58 ASSERT_require(alignment > 0);
59 T almt = static_cast<T>(alignment);
60 return (address / almt) * almt;
61}
62
119class MemoryMap: public Sawyer::Container::AddressMap<Address, uint8_t>, public Sawyer::SharedObject {
120public:
123
124 typedef uint8_t Value;
134
136 struct Attach { // For consistency with other <Feature>::Boolean types
137 enum Boolean {
139 YES
140 };
141 };
142
144 enum class Clobber {NO, YES};
145
146private:
147 ByteOrder::Endianness endianness_;
148 std::string name_;
149
150#ifdef ROSE_ENABLE_BOOST_SERIALIZATION
151private:
152 friend class boost::serialization::access;
153
154 template<class S>
155 void serialize(S &s, const unsigned /*version*/) {
156 s.template register_type<AllocatingBuffer>();
157 s.template register_type<MappedBuffer>();
158 s.template register_type<NullBuffer>();
159 s.template register_type<StaticBuffer>();
160 s & BOOST_SERIALIZATION_BASE_OBJECT_NVP(Super);
161 s & BOOST_SERIALIZATION_NVP(endianness_);
162 }
163#endif
164
165public:
166
167 // Whoever pollutes all namespaces with these common word preprocessor symbols is a lunatic!
168# if defined(READABLE) || defined(WRITABLE) || defined(EXECUTABLE) || defined(IMMUTABLE) || defined(PRIVATE)
169# ifdef _MSC_VER
170# pragma message("Undefining common words from the global namespace: READABLE, WRITABLE, EXECUTABLE, IMMUTABLE, PRIVATE")
171# else
172# warning "Undefining common words from the global namespace: READABLE, WRITABLE, EXECUTABLE, IMMUTABLE, PRIVATE"
173# endif
174# undef READABLE
175# undef WRITABLE
176# undef EXECUTABLE
177# undef IMMUTABLE
178# undef PRIVATE
179# endif
180
181 // Accessibility flags
182 static const unsigned NO_ACCESS = 0;
183 static const unsigned READABLE = Sawyer::Access::READABLE;
184 static const unsigned WRITABLE = Sawyer::Access::WRITABLE;
185 static const unsigned EXECUTABLE = Sawyer::Access::EXECUTABLE;
186 static const unsigned IMMUTABLE = Sawyer::Access::IMMUTABLE;
187 static const unsigned PRIVATE = Sawyer::Access::PRIVATE;
188 static const unsigned INITIALIZED = 0x00000200; // Partitioner2: initialized memory even if writable
189
190 // Aggregate accessibility flags
191 static const unsigned READ_WRITE = READABLE | WRITABLE;
192 static const unsigned READ_EXECUTE = READABLE | EXECUTABLE;
193 static const unsigned READ_WRITE_EXECUTE = READABLE | WRITABLE | EXECUTABLE;
194
195 // These bits are reserved for use in ROSE
196 static const unsigned RESERVED_ACCESS_BITS = 0x0000ffff;
197
198
199public:
202 public:
203 Exception(const std::string &mesg, const MemoryMap::Ptr map): Rose::Exception(mesg), map(map) {}
204 virtual ~Exception() throw() {}
205 virtual std::string leader(std::string dflt="memory map problem") const;
206 virtual std::string details(bool) const;
207 virtual void print(std::ostream&, bool verbose=true) const;
208 friend std::ostream& operator<<(std::ostream&, const Exception&);
209 public:
211 };
212
217 struct Inconsistent : public Exception {
218 Inconsistent(const std::string &mesg, const MemoryMap::Ptr &map,
219 const AddressInterval &new_range, const Segment &new_segment,
220 const AddressInterval &old_range, const Segment &old_segment)
221 : Exception(mesg, map),
222 new_range(new_range), old_range(old_range),
223 new_segment(new_segment), old_segment(old_segment) {}
224 virtual ~Inconsistent() throw() {}
225 virtual void print(std::ostream&, bool verbose=true) const;
226 friend std::ostream& operator<<(std::ostream&, const Inconsistent&);
227 AddressInterval new_range, old_range;
228 Segment new_segment, old_segment;
229 };
230
232 struct NotMapped : public Exception {
233 NotMapped(const std::string &mesg, const MemoryMap::Ptr &map, Address va)
234 : Exception(mesg, map), va(va) {}
235 virtual ~NotMapped() throw() {}
236 virtual void print(std::ostream&, bool verbose=true) const;
237 friend std::ostream& operator<<(std::ostream&, const NotMapped&);
238 Address va;
239 };
240
242 struct NoFreeSpace : public Exception {
243 NoFreeSpace(const std::string &mesg, const MemoryMap::Ptr &map, size_t size)
244 : Exception(mesg, map), size(size) {}
245 virtual ~NoFreeSpace() throw() {}
246 virtual void print(std::ostream&, bool verbose=true) const;
247 friend std::ostream& operator<<(std::ostream&, const NoFreeSpace&);
248 size_t size;
249 };
250
252 struct SyntaxError: public Exception {
253 SyntaxError(const std::string &mesg, const MemoryMap::Ptr &map, const std::string &filename,
254 unsigned linenum, int colnum=-1)
256 virtual ~SyntaxError() throw() {}
257 virtual void print(std::ostream&, bool verbose=true) const;
258 friend std::ostream& operator<<(std::ostream&, const SyntaxError&);
259 std::string filename;
260 unsigned linenum;
261 int colnum;
262 };
263
265 class LocatorError: public Exception {
266 public:
267 LocatorError(const std::string &mesg, const std::string &locatorString, const size_t index)
268 : Exception(mesg + "\n" +
269 " locator string: \"" + locatorString + "\"\n"
270 " error at " + std::string(7 + index, '-') + "^",
271 MemoryMap::Ptr()) {}
272 virtual ~LocatorError() throw() {}
273 };
274
275private:
276 // Address, size, and permissions parsed from "[ADDR][+SIZE][=PERM]".
277 struct AddrSizePerm {
278 Sawyer::Optional<Address> addr; // address if one was parsed at the beginning of the string
279 size_t sizeAt = 0; // string index where we tried to parse the size "+" character
280 Sawyer::Optional<uint64_t> size; // size if one was parsed
281 size_t permAt = 0; // string index where we tried to parse the permission "=" character.
282 Sawyer::Optional<unsigned> perm; // union of permissions if the leading "=" was present.
283 };
284
285protected:
287 MemoryMap(): endianness_(ByteOrder::ORDER_UNSPECIFIED) {}
288
289public:
291 static Ptr instance() {
292 return Ptr(new MemoryMap);
293 }
294
299 return Ptr(new MemoryMap(*this));
300 }
301
309 ByteOrder::Endianness byteOrder() const { return endianness_; }
310 void byteOrder(ByteOrder::Endianness order) { endianness_ = order; }
318 const std::string& name() const;
319 void name(const std::string&);
322 // Note that the order of the enum members is for backward compatibility with an older version of insertFile whose third
323 // argument was "bool writable = false" (MAP_RDONLY, but now intended to be MAP_PRIVATE) and when it was true was the same
324 // as MAP_READWRITE.
325 //
328 MAP_PRIVATE = 0,
330 MAP_READWRITE = 1,
332 MAP_RDONLY = 2
334 };
335
340 size_t insertFile(const std::string &fileName, Address va, InsertFileMapMode mode = MAP_PRIVATE, std::string segmentName = "");
341
417 AddressInterval insertFile(const std::string &locatorString);
418
420 static std::string insertFileDocumentation();
421
448 AddressInterval insertData(const std::string &locatorString);
449
451 static std::string insertDataDocumentation();
452
457 void adjustMap(const std::string &locatorString);
458
460 static std::string adjustMapDocumentation();
461
462
475
479 static std::vector<ProcessMapRecord> readProcessMap(pid_t);
480
481#ifdef BOOST_WINDOWS
482 void insertProcess(int pid, Attach::Boolean attach);
483#else
485 void insertProcess(pid_t pid, Attach::Boolean attach);
486#endif
487
491 void insertProcess(const std::string &locatorString);
492
496 bool insertProcessPid(pid_t, const AddressInterval &where, unsigned accessibility, const std::string &name);
497 void insertProcessPid(pid_t, const std::vector<ProcessMapRecord>&);
498 bool insertProcessMemory(int memFile, const AddressInterval &where, unsigned accessibility, std::string name);
502 static std::string insertProcessDocumentation();
503
517 AddressIntervalSet linkTo(const MemoryMap::Ptr &source, const AddressIntervalSet &where, Clobber = Clobber::YES);
518 AddressIntervalSet linkTo(const MemoryMap::Ptr &source, const AddressInterval &where, Clobber = Clobber::YES);
531 MemoryMap::Ptr align(Address lowAlignment, Address highAlignment) const;
532
538 static std::pair<Buffer::Ptr, std::string> copyFromFile(int fd, const AddressInterval&);
539
541 void eraseZeros(size_t minsize);
542
554
562
564 size_t readQuick(void *buf, Address startVa, size_t desired) const {
565 return at(startVa).limit(desired).require(READABLE).read((uint8_t*)buf).size();
566 }
567
580 std::string readString(Address startVa, size_t desired, int(*validChar)(int)=NULL, int(*invalidChar)(int)=NULL,
581 unsigned requiredPerms=READABLE, unsigned prohibitedPerms=0, char terminator='\0') const;
582
588 template<typename U>
590 U val = 0;
591 if (at(startVa).limit(sizeof val).read((uint8_t*)&val).size() != sizeof val)
592 return Sawyer::Nothing();
593 ByteOrder::convert((void*)&val, sizeof val, endianness_, ByteOrder::hostOrder());
594 return val;
595 }
596
603 uint64_t val = 0;
604 if (at(startVa).limit(sizeof val).read((uint8_t*)&val).size() != sizeof val)
605 return Sawyer::Nothing();
606 ByteOrder::convert((void*)&val, sizeof val, endianness_, ByteOrder::hostOrder());
607 return val;
608 }
609
614 size_t writeUnsigned(uint32_t value, Address startVa) {
615 return at(startVa).limit(sizeof(uint32_t)).write((const uint8_t*)(&value)).size();
616 }
617
622 size_t writeUnsigned(uint64_t value, Address startVa) {
623 return at(startVa).limit(sizeof(uint64_t)).write((const uint8_t*)(&value)).size();
624 }
625
630
632 SgUnsignedCharList readVector(Address startVa, size_t desired, unsigned requiredPerms=READABLE) const;
633
635 size_t writeQuick(const void *buf, Address startVa, size_t desired) {
636 return at(startVa).limit(desired).require(WRITABLE).write((const uint8_t*)buf).size();
637 }
638
646 Sawyer::Optional<Address> findAny(const Extent &limits, const std::vector<uint8_t> &bytesToFind,
647 unsigned requiredPerms=READABLE, unsigned prohibitedPerms=0) const;
648 Sawyer::Optional<Address> findAny(const AddressInterval &limits, const std::vector<uint8_t> &bytesToFind,
649 unsigned requiredPerms=READABLE, unsigned prohibitedPerms=0) const;
657 Sawyer::Optional<Address> findSequence(const AddressInterval &interval, const std::vector<uint8_t> &sequence) const;
658
662 void dump(FILE*, const char *prefix="") const;
663 void dump(std::ostream&, std::string prefix="") const;
664 void print(std::ostream &o, std::string prefix="") const { dump(o, prefix); }
665 void dump() const; // mostly for calling from within GDB or similar
683
685 static std::string segmentTitle(const Segment&);
686
687 friend std::ostream& operator<<(std::ostream&, const MemoryMap&);
688
694
702 static std::tuple<std::vector<std::tuple<std::string /*name*/, std::string /*value*/, size_t /*input_idx*/>>,
703 std::string /*following*/, size_t /*following_idx*/>
704 parseNameValuePairs(const std::string &input);
705};
706
707} // namespace
708} // namespace
709
710// Register the types needed for serialization since some of them are derived from polymorphic class templates.
711#ifdef ROSE_ENABLE_BOOST_SERIALIZATION
714BOOST_CLASS_EXPORT_KEY(Rose::BinaryAnalysis::MemoryMap::NullBuffer);
716#endif
717
718#endif
719#endif
A contiguous range of values.
Definition rangemap.h:50
Exception for MemoryMap operations.
Definition MemoryMap.h:201
MemoryMap::Ptr map
Map that caused the exception if available, null otherwise.
Definition MemoryMap.h:210
virtual std::string leader(std::string dflt="memory map problem") const
Leading part of the error message.
virtual std::string details(bool) const
Details emitted on following lines, indented two spaces.
Exception thrown for an error in a locator string.
Definition MemoryMap.h:265
An efficient mapping from an address space to stored data.
Definition MemoryMap.h:119
AddressInterval insertData(const std::string &locatorString)
Insert data into a memory map.
size_t writeUnsigned(uint64_t value, Address startVa)
Write a long unsigned value.
Definition MemoryMap.h:622
MemoryMapPtr Ptr
Reference counting pointer.
Definition MemoryMap.h:122
MemoryMap::Ptr align(Address lowAlignment, Address highAlignment) const
Create a new map by padding and aligning segments.
ByteOrder::Endianness byteOrder() const
Property: Byte order.
Definition MemoryMap.h:309
Sawyer::Optional< Address > 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.
size_t readQuick(void *buf, Address startVa, size_t desired) const
Read data into buffer.
Definition MemoryMap.h:564
void dump(std::ostream &, std::string prefix="") const
Prints the contents of the map for debugging.
Sawyer::Optional< uint8_t > readByte(Address) const
Read a byte from memory.
bool insertProcessMemory(int memFile, const AddressInterval &where, unsigned accessibility, std::string name)
Insert part of another process's memory into this memory map.
static std::vector< ProcessMapRecord > readProcessMap(pid_t)
Obtain the memory map information for a process.
size_t writeQuick(const void *buf, Address startVa, size_t desired)
Write data from buffer.
Definition MemoryMap.h:635
static std::string insertDataDocumentation()
Documentation string for insertData.
static std::string adjustMapDocumentation()
Documentation string for adjustMap.
bool combineAdjacentSegments()
Combine adjacent segments.
bool shrinkUnshare()
Shrink buffers and remove sharing.
size_t insertFile(const std::string &fileName, Address va, InsertFileMapMode mode=MAP_PRIVATE, std::string segmentName="")
Insert file contents into memory map.
std::string readString(Address 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.
static Ptr instance()
Construct an empty memory map.
Definition MemoryMap.h:291
void name(const std::string &)
Property: Name.
static std::tuple< std::vector< std::tuple< std::string, std::string, size_t > >, std::string, size_t > parseNameValuePairs(const std::string &input)
Parse comma-separated name=value pairs.
InsertFileMapMode
Mapping mode for insertFile.
Definition MemoryMap.h:327
@ MAP_PRIVATE
File is mapped privately.
Definition MemoryMap.h:328
@ MAP_READWRITE
File is mapped with read and write permission.
Definition MemoryMap.h:330
@ MAP_RDONLY
File is mapped with read-only permission.
Definition MemoryMap.h:332
bool insertProcessPid(pid_t, const AddressInterval &where, unsigned accessibility, const std::string &name)
Insert part of another process's memory into this memory map.
Combinatorics::Hasher & hash(Combinatorics::Hasher &) const
Compute a hash of the entire memory contents.
void print(std::ostream &o, std::string prefix="") const
Prints the contents of the map for debugging.
Definition MemoryMap.h:664
const std::string & name() const
Property: Name.
void eraseZeros(size_t minsize)
Erases regions of zero bytes that are executable and readable and at least minsize in size.
Ptr shallowCopy()
Create a new copy of the memory map.
Definition MemoryMap.h:298
void insertProcess(const std::string &locatorString)
Insert the memory of some other process into this memory map.
AddressIntervalSet linkTo(const MemoryMap::Ptr &source, const AddressIntervalSet &where, Clobber=Clobber::YES)
Insert part of another map by reference.
Sawyer::Optional< U > readUnsigned(Address startVa) const
Read an unsigned value.
Definition MemoryMap.h:589
void insertProcess(pid_t pid, Attach::Boolean attach)
Insert the memory of some other process into this memory map.
static std::pair< Buffer::Ptr, std::string > copyFromFile(int fd, const AddressInterval &)
Copy part of a file into a buffer.
void dump() const
Prints the contents of the map for debugging.
AddressIntervalSet linkTo(const MemoryMap::Ptr &source, const AddressInterval &where, Clobber=Clobber::YES)
Insert part of another map by reference.
SgUnsignedCharList readVector(Address startVa, size_t desired, unsigned requiredPerms=READABLE) const
Read quickly into a vector.
Sawyer::Optional< Address > findSequence(const AddressInterval &interval, const std::vector< uint8_t > &sequence) const
Search for a byte sequence.
MemoryMap()
Constructs an empty memory map.
Definition MemoryMap.h:287
Sawyer::Optional< uint64_t > readLongUnsinged(Address startVa) const
Read a long unsigned value.
Definition MemoryMap.h:602
void byteOrder(ByteOrder::Endianness order)
Property: Byte order.
Definition MemoryMap.h:310
Sawyer::Optional< Address > findAny(const AddressInterval &limits, const std::vector< uint8_t > &bytesToFind, unsigned requiredPerms=READABLE, unsigned prohibitedPerms=0) const
Search for any byte.
static std::string insertFileDocumentation()
Documentation string for insertFile.
void dump(FILE *, const char *prefix="") const
Prints the contents of the map for debugging.
static std::string insertProcessDocumentation()
Documentation string for insertProcess.
AddressInterval insertFile(const std::string &locatorString)
Insert file contents into memory map.
size_t writeUnsigned(uint32_t value, Address startVa)
Write an unsigned value.
Definition MemoryMap.h:614
static Sawyer::Result< AddrSizePerm, std::pair< std::string, size_t > > parseAddrSizePerm(const std::string &)
Parse input of the form "[ADDR][+SIZE][=[r][w][x]]".
void insertProcessPid(pid_t, const std::vector< ProcessMapRecord > &)
Insert part of another process's memory into this memory map.
void adjustMap(const std::string &locatorString)
Adjusts a memory map according to the locator string.
Clobber
Overwrite (parts of) existing segments?
Definition MemoryMap.h:144
Base class for all ROSE exceptions.
Constraints are used to select addresses from a memory map.
Definition AddressMap.h:76
A mapping from address space to values.
Sawyer::Container::Interval< Address > read(Value *buf, const AddressMapConstraints< const AddressMap > &c, MatchFlags flags=0) const
Reads data into the supplied buffer.
AddressMapConstraints< const AddressMap > at(Address x) const
Constraint: anchor point.
AddressMapConstraints< const AddressMap > limit(size_t x) const
Constraint: limit matched size.
Allocates memory as needed.
Base class for all buffers.
Definition Buffer.h:23
Interval::Value size() const
Returns the number of values represented by this container.
Buffer that has no data.
Definition NullBuffer.h:22
Base class for testing segment constraints.
Definition AddressMap.h:55
Points to static data.
Represents no value.
Definition Optional.h:36
Holds a value or nothing.
Definition Optional.h:56
Result containing a value or an error.
Definition Result.h:315
Base class for reference counted objects.
void convert(void *bytes, size_t nbytes, Endianness from, Endianness to)
Convert data from one byte order to another in place.
Endianness hostOrder()
Byte order of host machine.
Sawyer::SharedPointer< MemoryMap > MemoryMapPtr
Reference counting pointer.
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:44
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:57
The ROSE library.
Attach with ptrace first when reading a process?
Definition MemoryMap.h:136
@ YES
Attach with ptrace, get memory, then detach.
Definition MemoryMap.h:139
@ NO
Assume ptrace is attached and process is stopped.
Definition MemoryMap.h:138
Exception for an inconsistent mapping.
Definition MemoryMap.h:217
Exception thrown by find_free() when there's not enough free space left.
Definition MemoryMap.h:242
Exception for when we try to access a virtual address that isn't mapped.
Definition MemoryMap.h:232
Information about a process map.
Definition MemoryMap.h:464
std::string deviceName
Starting byte offset in the file.
Definition MemoryMap.h:468
Address fileOffset
The accessibility flags.
Definition MemoryMap.h:467
std::string comment
Inode on the device, or zero.
Definition MemoryMap.h:470
unsigned accessibility
Mapped virtual addresses.
Definition MemoryMap.h:466
size_t inode
The device from which the data is mapped, or "00:00".
Definition MemoryMap.h:469
Exception thrown by load() when there's a syntax error in the index file.
Definition MemoryMap.h:252
unsigned linenum
Line number (1 origin) where error occurred.
Definition MemoryMap.h:260
int colnum
Optional column number (0-origin; negative if unknown).
Definition MemoryMap.h:261
std::string filename
Name of index file where error occurred.
Definition MemoryMap.h:259