diff options
Diffstat (limited to 'plugins/python/cglimpse/entropy.py')
-rw-r--r-- | plugins/python/cglimpse/entropy.py | 137 |
1 files changed, 102 insertions, 35 deletions
diff --git a/plugins/python/cglimpse/entropy.py b/plugins/python/cglimpse/entropy.py index f090624..5c4df5a 100644 --- a/plugins/python/cglimpse/entropy.py +++ b/plugins/python/cglimpse/entropy.py @@ -1,22 +1,32 @@ import math +from gi.repository import Gdk +from pychrysalide.glibext import ConfigParam from .method import GlimpseMethod class ShannonEntropy(GlimpseMethod): - def __init__(self, builder): - """Prepare a Shannon entropy display.""" - super(ShannonEntropy, self).__init__(builder) + @staticmethod + def setup_config(config): + """Register the configuration parameters for the method.""" - button = builder.get_object('shannon_color') - button.connect('color-set', self._on_color_set) + color = Gdk.RGBA() + color.parse('#3465A4') - self._on_color_set(button) + param = ConfigParam('cglimpse.shannon.color', ConfigParam.ConfigParamType.COLOR, color) + config.add(param) - self._step = 0x80 + param = ConfigParam('cglimpse.shannon.step', ConfigParam.ConfigParamType.ULONG, 0x80) + config.add(param) + + + def __init__(self, builder, config, update_cb): + """Prepare a Shannon entropy display.""" + + super(ShannonEntropy, self).__init__(builder, config, update_cb) self._v_legend = 'Entropy' self._h_legend = 'Byte offsets' @@ -24,17 +34,64 @@ class ShannonEntropy(GlimpseMethod): self._x_range = [ 0, 1024, 10240 ] self._y_range = [ 0.0, 0.25, 1.0 ] - self._size = None + self._coverage = None self._values = [] + button = builder.get_object('shannon_color') + button.connect('color-set', self._on_color_set) + + param = config.search('cglimpse.shannon.color') + color = param.value + + self._color = [ color.red, color.green, color.blue, color.alpha ] + self._shadow_color = [ color.red * 0.5, color.green * 0.5, color.blue * 0.5, color.alpha ] + + button.set_rgba(param.value) + + scale = builder.get_object('shannon_step') + scale.connect('format-value', self._on_scale_format_value) + scale.connect('value-changed', self._on_scale_value_changed) + + param = config.search('cglimpse.shannon.step') + step = param.value + + self._step = step + + scale.set_value(step) + def _on_color_set(self, button): """React on color chosen for the rendering.""" color = button.get_rgba() + self._color = [ color.red, color.green, color.blue, color.alpha ] self._shadow_color = [ color.red * 0.5, color.green * 0.5, color.blue * 0.5, color.alpha ] + param = self._config.search('cglimpse.shannon.color') + param.value = color + + self._update_cb() + + + def _on_scale_value_changed(self, scale): + """React when the range value changes.""" + + step = int(scale.get_value()) + + self._step = step + + param = self._config.search('cglimpse.shannon.step') + param.value = step + + self._update_cb() + + + def _on_scale_format_value(self, scale, value): + """Change how the scale value is displayed.""" + + return '0x%x' % int(value) + def format_legend(self, value, vert): """Build the label used for a rule.""" @@ -44,42 +101,53 @@ class ShannonEntropy(GlimpseMethod): else: + multi = 1 + scale = [ ' kb', ' Mb', ' Gb', ' Tb' ] suffix = '' + remaining = value + for i in range(len(scale)): - if value < 1024: + if remaining < 1024: break - value /= 1024 + multi *= 1024 + + remaining /= 1024 suffix = scale[i] - text = '%u%s' % (value, suffix) + if value % multi == 0: + text = '%u%s' % (remaining, suffix) + else: + text = '%.1f%s' % (value / multi, suffix) return text - def update(self, data): - """Provide a description for the method.""" + def update(self, data, coverage): + """Compute internal values for the method.""" - self._size = len(data) + self._coverage = coverage - step = 2 ** math.ceil(math.log(self._size / 10, 2)) + size = self._coverage[1] - self._coverage[0] - self._x_range = [ 0, step, 10 * step ] + step = math.ceil(size / 10) + + self._x_range = [ coverage[0], step, coverage[0] + 10 * step ] self._values = [] - for i in range(0, self._size, self._step): + for i in range(self._x_range[0], self._x_range[2], self._step): counter = [ 0 for i in range(256) ] start = i end = i + self._step - if end > self._size: - end = self._size + if end > self._coverage[1]: + end = self._coverage[1] for b in data[start : end]: counter[b] += 1 @@ -97,31 +165,29 @@ class ShannonEntropy(GlimpseMethod): def render(self, cr, area): """Draw the bytes distribution for the current binary, if any.""" - step = 2 ** math.ceil(math.log(self._size / 10, 2)) + size = self._coverage[1] - self._coverage[0] - if self._size % step == 0: - full_size = self._size - else: - full_size = (self._size + step - 1) & ~(step - 1) + step = math.ceil(size / 10) - start = 0 + start = self._coverage[0] last_x = area[0] last_y = area[1] + area[3] - (area[3] * self._values[0]) cr.move_to(last_x, last_y + 2) - for i in range(0, self._size, self._step): + for i in range(self._x_range[0], self._x_range[2], self._step): end = i + self._step - if end > self._size: - end = self._size + if end > self._coverage[1]: + end = self._coverage[1] - x = area[0] + ((end - start) * area[2]) / full_size - y = area[1] + area[3] - (area[3] * self._values[int(i / self._step)]) + x = area[0] + ((end - start) * area[2]) / (10 * step) + y = area[1] + area[3] - (area[3] * self._values[int((i - self._x_range[0]) / self._step)]) if last_y != y: cr.line_to(last_x, y + 2) + last_y = y cr.line_to(x, y + 2) @@ -136,18 +202,19 @@ class ShannonEntropy(GlimpseMethod): last_y = area[1] + area[3] - (area[3] * self._values[0]) cr.move_to(last_x, last_y) - for i in range(0, self._size, self._step): + for i in range(self._x_range[0], self._x_range[2], self._step): end = i + self._step - if end > self._size: - end = self._size + if end > self._coverage[1]: + end = self._coverage[1] - x = area[0] + ((end - start) * area[2]) / full_size - y = area[1] + area[3] - (area[3] * self._values[int(i / self._step)]) + x = area[0] + ((end - start) * area[2]) / (10 * step) + y = area[1] + area[3] - (area[3] * self._values[int((i - self._x_range[0]) / self._step)]) if last_y != y: cr.line_to(last_x, y) + last_y = y cr.line_to(x, y) |