From b9721045c0c29c4f7f4bb6a5b54a22f133520098 Mon Sep 17 00:00:00 2001 From: cracked-machine Date: Fri, 9 Feb 2024 18:37:10 +0000 Subject: [PATCH] added skippable regions --- doc/example/report.md | 10 ++-- doc/example/report_cropped.png | Bin 0 -> 13552 bytes doc/example/report_full.png | Bin 0 -> 13552 bytes mm/diagram.py | 86 ++++++++++++++++++++++++++++++--- mm/types.py | 43 ++++++++++++++--- tests/test_args.py | 8 +-- tests/test_scaling.py | 37 +++++++++++--- tests/test_skip_regions.py | 59 ++++++++++++++++++++++ 8 files changed, 212 insertions(+), 31 deletions(-) create mode 100644 doc/example/report_cropped.png create mode 100644 doc/example/report_full.png create mode 100644 tests/test_skip_regions.py diff --git a/doc/example/report.md b/doc/example/report.md index ff16297..03c470b 100644 --- a/doc/example/report.md +++ b/doc/example/report.md @@ -1,8 +1,8 @@ ![memory map diagram](report.png) |name|origin|size|remaining|collisions |:-|:-|:-|:-|:-| -|kernel|0x10|0x50|-0x10|{'rootfs': '0x50'}| -|uboot|0xD0|0x50|-0x10|{'uboot-scr': '0x110'}| -|rootfs|0x50|0x30|0x10|{'kernel': '0x50'}| -|dtb|0x90|0x30|0x10|{}| -|uboot-scr|0x110|0x30|0x50|{'uboot': '0x110'}| +|kernel|0x10|0x50|-0x10|{'rootfs': '0x50'}| +|uboot|0xD0|0x50|-0x10|{'uboot-scr': '0x110'}| +|rootfs|0x50|0x30|0x10|{'kernel': '0x50'}| +|dtb|0x90|0x30|0x10|{}| +|uboot-scr|0x110|0x30|0x50|{'uboot': '0x110'}| diff --git a/doc/example/report_cropped.png b/doc/example/report_cropped.png new file mode 100644 index 0000000000000000000000000000000000000000..fd4e37760c84b9f367f7042cb0f4439f02d238ae GIT binary patch literal 13552 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°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°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 self.skip_threshold: + + # dont forget the image is upside down at this stage, so upper and lower are reversed. + (left, upper, right, lower) = (0, address_cursor - 10, img_to_crop.width, end_addr_val + 10) + cropped_img = img_to_crop.crop((left, upper, right, lower)) + region_cluster_list.append(cropped_img) + + # move the cursor up past the end of the current region and the empty space + address_cursor = end_addr_val + int(region.remain, 16) + + # join all the cropped images together into a smaller main image + skip_region = mm.types.SkippableRegion(size=hex(40)) + skip_region.create_img(img_width=(self.width - 20), font_size=self.default_region_text_size) + total_cropped_height = sum(r.height for r in region_cluster_list) + total_cropped_height = total_cropped_height + (len(region_cluster_list) * skip_region.img.height) + 20 + img_main_cropped = PIL.Image.new("RGB", (self.width, total_cropped_height), color=self.bgcolour) + y_pos = 0 + for region_cluster in region_cluster_list: + img_main_cropped.paste(region_cluster, (0, y_pos)) + y_pos = y_pos + region_cluster.height + + img_main_cropped.paste(skip_region.img, (10, y_pos)) + y_pos = y_pos + skip_region.img.height + + # Diagram End Address Text + diagram_end_addr_val = self.height + diagram_end_addr_label = mm.types.TextLabel(hex(diagram_end_addr_val), self.fixed_legend_text_size) + img_main_cropped.paste(diagram_end_addr_label.img, (0, img_main_cropped.height - diagram_end_addr_label.height - 10)) + + # Diagram End Dash Line + line_width = 1 + line_canvas = PIL.ImageDraw.Draw(img_main_cropped) + dash_gap = 4 + dash_len = dash_gap / 2 + for x in range(diagram_end_addr_label.width * 2, self.width - 10, dash_gap): + line_canvas.line((x, img_main_cropped.height - diagram_end_addr_label.height - 3, + x + dash_len, + img_main_cropped.height - diagram_end_addr_label.height - 3), + fill="black", + width=line_width) + + # no large empty regions were found so just copy in the existing image + if not region_cluster_list: + img_main_cropped = img_to_crop + + img_main_cropped = img_main_cropped.rotate(180) + img_file_path = pathlib.Path(self.args.out).stem + "_cropped.png" + img_main_cropped.save(pathlib.Path(self.args.out).parent / img_file_path) def _create_markdown(self, region_list: List[mm.types.MemoryRegion]): with open(self.args.out, "w") as f: diff --git a/mm/types.py b/mm/types.py index 452c4d9..3557437 100644 --- a/mm/types.py +++ b/mm/types.py @@ -165,6 +165,41 @@ def create_img(self, img_width: int, font_size: int): self.img = region_img +@typeguard.typechecked +class SkippableRegion(Region): + + def __init__(self, size: str): + + self.name: str = "~~~~~ SKIPPED ~~~~~" + + super().__init__(self.name, "0x0", size) + + def create_img(self, img_width: int, font_size: int): + + logging.info(self) + if not self.size: + logging.warning("Zero size region skipped") + return None + + # MemoryRegion Blocks and text + region_img = PIL.Image.new("RGBA", (img_width + 1, self.size), color="white") + self.region_canvas = PIL.ImageDraw.Draw(region_img) + + # height is -1 to avoid clipping the top border + self.region_canvas.rectangle( + (0, 0, img_width, self.size - 1), + fill="oldlace", + outline="black", + width=1, + ) + + # draw name text + region_w, region_h = region_img.size + region_img.paste(TextLabel(text=self.name, font_size=font_size).img, (region_w // 5, region_h // 3)) + + self.img = region_img + + @typeguard.typechecked class TextLabel(): def __init__(self, text: str, font_size: int): @@ -207,11 +242,3 @@ def _create_img(self): # the final diagram image will be flipped so start with the text upside down self.img = self.img.rotate(180) - - -@typeguard.typechecked -class SkippableRegion(Region): - pass - - - diff --git a/tests/test_args.py b/tests/test_args.py index 0570901..a879e0c 100644 --- a/tests/test_args.py +++ b/tests/test_args.py @@ -64,8 +64,8 @@ def test_valid_default_out_arg(): '0x10', '0x10']): mm.diagram.MemoryMap() - assert report.exists() - assert image.exists() + assert report.is_file + assert image.is_file def test_invalid_duplicate_name_arg(): @@ -98,5 +98,5 @@ def test_valid_custom_out_arg(): "-o", str(report)]): mm.diagram.MemoryMap() - assert report.exists() - assert image.exists() + assert report.is_file + assert image.is_file diff --git a/tests/test_scaling.py b/tests/test_scaling.py index 50f43c5..9b757cf 100644 --- a/tests/test_scaling.py +++ b/tests/test_scaling.py @@ -10,10 +10,15 @@ def test_scaling_x1(): default_diagram_width = 400 requested_diagram_height = 400 requested_scale = 1 + report_path = pathlib.Path(f"/tmp/pytest/{__name__}.md") - image_path = pathlib.Path(f"/tmp/pytest/{__name__}.png") report_path.unlink(missing_ok=True) - image_path.unlink(missing_ok=True) + + image_path_full = pathlib.Path(f"/tmp/pytest/{__name__}_full.png") + image_path_full.unlink(missing_ok=True) + + image_path_cropped = pathlib.Path(f"/tmp/pytest/{__name__}_cropped.png") + image_path_cropped.unlink(missing_ok=True) with unittest.mock.patch('sys.argv', ['mmap_digram.diagram', @@ -32,21 +37,33 @@ def test_scaling_x1(): str(requested_diagram_height)]): d = mm.diagram.MemoryMap() - outimg = PIL.Image.open(str(image_path)) + assert image_path_full.is_file + outimg = PIL.Image.open(str(image_path_full)) assert d.height == requested_diagram_height * requested_scale assert d.width == default_diagram_width * requested_scale assert outimg.size == (d.width, d.height) + assert image_path_cropped.is_file + outimg = PIL.Image.open(str(image_path_cropped)) + assert d.height == requested_diagram_height * requested_scale + assert d.width == default_diagram_width * requested_scale + assert outimg.size == (d.width, 272) + def test_scaling_x2(): """ """ default_diagram_width = 400 requested_diagram_height = 400 requested_scale = 2 + report_path = pathlib.Path(f"/tmp/pytest/{__name__}.md") - image_path = pathlib.Path(f"/tmp/pytest/{__name__}.png") report_path.unlink(missing_ok=True) - image_path.unlink(missing_ok=True) + + image_path_full = pathlib.Path(f"/tmp/pytest/{__name__}_full.png") + image_path_full.unlink(missing_ok=True) + + image_path_cropped = pathlib.Path(f"/tmp/pytest/{__name__}_cropped.png") + image_path_cropped.unlink(missing_ok=True) with unittest.mock.patch('sys.argv', ['mmap_digram.diagram', @@ -64,7 +81,15 @@ def test_scaling_x2(): "-s", str(requested_scale)]): d = mm.diagram.MemoryMap() - outimg = PIL.Image.open(str(image_path)) + + assert image_path_full.is_file + outimg = PIL.Image.open(str(image_path_full)) assert d.height == requested_diagram_height * requested_scale assert d.width == default_diagram_width * requested_scale assert outimg.size == (d.width, d.height) + + assert image_path_cropped.is_file + outimg = PIL.Image.open(str(image_path_cropped)) + assert d.height == requested_diagram_height * requested_scale + assert d.width == default_diagram_width * requested_scale + assert outimg.size == (d.width, 272) diff --git a/tests/test_skip_regions.py b/tests/test_skip_regions.py new file mode 100644 index 0000000..137191e --- /dev/null +++ b/tests/test_skip_regions.py @@ -0,0 +1,59 @@ +import mm.diagram +import unittest +import mm.types +import pathlib +import PIL.Image + +# Check the output report at /tmp/pytest/tests.test_distance.md + + +def test_skip_region(): + """ """ + + report = pathlib.Path(f"/tmp/pytest/{__name__}.md") + image_full = pathlib.Path(f"/tmp/pytest/{__name__}_full.png") + image_crop_join = pathlib.Path(f"/tmp/pytest/{__name__}_cropped.png") + + report.unlink(missing_ok=True) + image_full.unlink(missing_ok=True) + image_crop_join.unlink(missing_ok=True) + + diagram_height = 1000 + with unittest.mock.patch('sys.argv', + ['mmap_digram.diagram', + 'kernel', + '0x10', + '0x30', + 'rootfs', + '0x50', + '0x30', + 'dtb', + '0x190', + '0x30', + "-o", str(report), + "-l", str(diagram_height)]): + + d = mm.diagram.MemoryMap() + for region in d._region_list: + if region.name == "kernel": + assert region._origin == "0x10" + assert region._size == "0x30" + assert region.remain == "0x10" + if region.name == "rootfs": + assert region._origin == "0x50" + assert region._size == "0x30" + assert region.remain == "0x110" + if region.name == "dtb": + assert region._origin == "0x190" + assert region._size == "0x30" + assert region.remain == "0x228" + + assert report.is_file + + assert image_full.is_file + assert PIL.Image.open(image_full).width == 400 + assert PIL.Image.open(image_full).height == 1000 + + assert image_crop_join.is_file + assert PIL.Image.open(image_crop_join).width == 400 + assert PIL.Image.open(image_crop_join).height == 316