about summary refs log tree commit diff stats
path: root/miasm2/core
diff options
context:
space:
mode:
Diffstat (limited to 'miasm2/core')
-rw-r--r--miasm2/core/bin_stream.py40
-rw-r--r--miasm2/core/graph.py35
-rw-r--r--miasm2/core/locationdb.py21
3 files changed, 81 insertions, 15 deletions
diff --git a/miasm2/core/bin_stream.py b/miasm2/core/bin_stream.py
index 8bd59467..af31a52c 100644
--- a/miasm2/core/bin_stream.py
+++ b/miasm2/core/bin_stream.py
@@ -160,63 +160,73 @@ class bin_stream(object):
 
 class bin_stream_str(bin_stream):
 
-    def __init__(self, input_str="", offset=0L, shift=0):
+    def __init__(self, input_str="", offset=0L, base_address=0, shift=None):
         bin_stream.__init__(self)
+        if shift is not None:
+            raise DeprecationWarning("use base_address instead of shift")
         self.bin = input_str
         self.offset = offset
-        self.shift = shift
+        self.base_address = base_address
         self.l = len(input_str)
 
     def _getbytes(self, start, l=1):
-        if start + l + self.shift > self.l:
+        if start + l - self.base_address > self.l:
             raise IOError("not enough bytes in str")
+        if start - self.base_address < 0:
+            raise IOError("Negative offset")
 
-        return super(bin_stream_str, self)._getbytes(start + self.shift, l)
+        return super(bin_stream_str, self)._getbytes(start - self.base_address, l)
 
     def readbs(self, l=1):
-        if self.offset + l + self.shift > self.l:
+        if self.offset + l - self.base_address > self.l:
             raise IOError("not enough bytes in str")
+        if self.offset - self.base_address < 0:
+            raise IOError("Negative offset")
         self.offset += l
-        return self.bin[self.offset - l + self.shift:self.offset + self.shift]
+        return self.bin[self.offset - l - self.base_address:self.offset - self.base_address]
 
     def __str__(self):
-        out = self.bin[self.offset + self.shift:]
+        out = self.bin[self.offset - self.base_address:]
         return out
 
     def setoffset(self, val):
         self.offset = val
 
     def getlen(self):
-        return self.l - (self.offset + self.shift)
+        return self.l - (self.offset - self.base_address)
 
 
 class bin_stream_file(bin_stream):
 
-    def __init__(self, binary, offset=0L, shift=0):
+    def __init__(self, binary, offset=0L, base_address=0, shift=None):
         bin_stream.__init__(self)
+        if shift is not None:
+            raise DeprecationWarning("use base_address instead of shift")
         self.bin = binary
         self.bin.seek(0, 2)
-        self.shift = shift
+        self.base_address = base_address
         self.l = self.bin.tell()
         self.offset = offset
 
     def getoffset(self):
-        return self.bin.tell() - self.shift
+        return self.bin.tell() + self.base_address
 
     def setoffset(self, val):
-        self.bin.seek(val + self.shift)
+        self.bin.seek(val - self.base_address)
     offset = property(getoffset, setoffset)
 
     def readbs(self, l=1):
-        if self.offset + l + self.shift > self.l:
+        if self.offset + l - self.base_address > self.l:
             raise IOError("not enough bytes in file")
+        if self.offset - self.base_address < 0:
+            raise IOError("Negative offset")
         return self.bin.read(l)
 
     def __str__(self):
         return str(self.bin)
 
     def getlen(self):
-        return self.l - (self.offset + self.shift)
+        return self.l - (self.offset - self.base_address)
 
 
 class bin_stream_container(bin_stream):
@@ -236,6 +246,8 @@ class bin_stream_container(bin_stream):
     def readbs(self, l=1):
         if self.offset + l > self.l:
             raise IOError("not enough bytes")
+        if self.offset < 0:
+            raise IOError("Negative offset")
         self.offset += l
         return self.bin.virt.get(self.offset - l, self.offset)
 
diff --git a/miasm2/core/graph.py b/miasm2/core/graph.py
index f61d1e67..e385b044 100644
--- a/miasm2/core/graph.py
+++ b/miasm2/core/graph.py
@@ -143,6 +143,14 @@ class DiGraph(object):
         return [x for x in self.heads_iter()]
 
     def find_path(self, src, dst, cycles_count=0, done=None):
+        """
+        Searches for paths from @src to @dst
+        @src: loc_key of basic block from which it should start
+        @dst: loc_key of basic block where it should stop
+        @cycles_count: maximum number of times a basic block can be processed
+        @done: dictionary of already processed loc_keys, it's value is number of times it was processed
+        @out: list of paths from @src to @dst
+        """
         if done is None:
             done = {}
         if dst in done and done[dst] > cycles_count:
@@ -157,6 +165,33 @@ class DiGraph(object):
                 if path and path[0] == src:
                     out.append(path + [dst])
         return out
+    
+    def find_path_from_src(self, src, dst, cycles_count=0, done=None):
+        """
+        This function does the same as function find_path.
+        But it searches the paths from src to dst, not vice versa like find_path.
+        This approach might be more efficient in some cases.
+        @src: loc_key of basic block from which it should start
+        @dst: loc_key of basic block where it should stop
+        @cycles_count: maximum number of times a basic block can be processed
+        @done: dictionary of already processed loc_keys, it's value is number of times it was processed
+        @out: list of paths from @src to @dst
+        """
+        
+        if done is None:
+            done = {}
+        if src == dst:
+            return [[src]]
+        if src in done and done[src] > cycles_count:
+            return [[]]
+        out = []
+        for node in self.successors(src):
+            done_n = dict(done)
+            done_n[src] = done_n.get(src, 0) + 1
+            for path in self.find_path_from_src(node, dst, cycles_count, done_n):
+                if path and path[len(path)-1] == dst:
+                    out.append([src] + path)
+        return out
 
     def nodeid(self, node):
         """
diff --git a/miasm2/core/locationdb.py b/miasm2/core/locationdb.py
index b6e60794..4c5da29e 100644
--- a/miasm2/core/locationdb.py
+++ b/miasm2/core/locationdb.py
@@ -204,6 +204,22 @@ class LocationDB(object):
         for name, loc_key in self._name_to_loc_key.iteritems():
             assert name in self._loc_key_to_names[loc_key]
 
+    def find_free_name(self, name):
+        """
+        If @name is not known in DB, return it
+        Else append an index to it corresponding to the next unknown name
+
+        @name: string
+        """
+        if self.get_name_location(name) is None:
+            return name
+        i = 0
+        while True:
+            new_name = "%s_%d" % (name, i)
+            if self.get_name_location(new_name) is None:
+                return new_name
+            i += 1
+
     def add_location(self, name=None, offset=None, strict=True):
         """Add a new location in the locationDB. Returns the corresponding LocKey.
         If @name is set, also associate a name to this new location.
@@ -252,7 +268,10 @@ class LocationDB(object):
             # Non-strict mode
             if name_loc_key is not None:
                 known_offset = self.get_offset_location(name_loc_key)
-                if known_offset != offset:
+                if known_offset is None:
+                    if offset is not None:
+                        self.set_location_offset(name_loc_key, offset)
+                elif known_offset != offset:
                     raise ValueError(
                         "Location with name '%s' already have an offset: 0x%x "
                         "(!= 0x%x)" % (name, offset, known_offset)