diff options
Diffstat (limited to 'miasm2/core')
| -rw-r--r-- | miasm2/core/bin_stream.py | 40 | ||||
| -rw-r--r-- | miasm2/core/graph.py | 35 | ||||
| -rw-r--r-- | miasm2/core/locationdb.py | 21 |
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) |