diff --git a/README.md b/README.md index 7f3ee89..0deb38e 100644 --- a/README.md +++ b/README.md @@ -46,25 +46,45 @@ python3 -m mm.diagram -h ``` usage: diagram.py [-h] [-o OUT] [-l LIMIT] [-t THRESHOLD] [-n NAME] [-f FILE] [-v] [--no_whitespace_trim] [regions ...] -Generate a diagram showing how binary regions co-exist within memory. +Tool for generating diagrams that show the mapping of regions in memory. positional arguments: - regions Sequence of region data. Should be tuples of name, origin and size: + regions Sequence of region data. Should be tuples of name, origin and size: + options: -h, --help show this help message and exit - -o OUT, --out OUT The path to the markdown output report file. Diagram and table images will be written using this path and name (using png extension). Default: - 'out/report.md' + -o OUT, --out OUT The path to the markdown output report file. + Diagram and table images will be written using this path and name (using png extension). + Default: 'out/report.md' -l LIMIT, --limit LIMIT - The 'height' in pixels and 'max address' in bytes for the diagram. Please use hex format. Ignored when using JSON file input. Memory regions exceeding - this value will be scaled to fit when drawn but collision measurements will use the original value. If you need to set 'height' and 'max address' to - different values, please use the JSON input file instead. + + The 'height' in pixels and 'max address' in bytes for the diagram. + Please use hex format. Ignored when using JSON file input. + Memory regions exceeding this value will be scaled to fit when drawn + but collision measurements will use the original value. + If you need to set 'height' and 'max address' to different values, + please use the JSON input file instead. -t THRESHOLD, --threshold THRESHOLD - The threshold for replacing large empty sections with 'SKIPPED' regions. Any space over this value will be replaced. Please use hex. Default = 0x16 + The threshold for replacing large empty sections with 'SKIPPED' regions. + Any space over this value will be replaced. Please use hex. Default = 0x16 -n NAME, --name NAME Provide a name for the memory map. Ignored when JSON file is provided. -f FILE, --file FILE JSON input file for multiple memory maps (and links) support. Please see docs/example for help. -v Enable debug output. - --no_whitespace_trim Force disable of whitespace trim in diagram images. If this option is set, diagram images may be created larger than requested. + --no_whitespace_trim Force disable of whitespace trim in diagram images. + If this option is set, diagram images may be created larger than requested. + + EXAMPLES + -------- + - Generate a map diagram called 'dram' that contains five regions called kernel, rootfs, dtb, uboot and uboot-scr where four of the five regions intersect/collide. + The default report output path is used. + + python3 -m mm.diagram kernel 0x10 0x50 rootfs 0x50 0x30 dtb 0x90 0x30 uboot 0xD0 0x50 uboot-scr 0x110 0x30 -l 0x3e8 -n dram + + - Using JSON many other options can be set. + Example json files can be found at https://cracked-machine.github.io/mmdiagram/examples.html + + python3 -m mm.diagram -f docs/example/example_two_maps.json ``` #### Examples diff --git a/mm/diagram.py b/mm/diagram.py index 3ab612f..70ad5a9 100644 --- a/mm/diagram.py +++ b/mm/diagram.py @@ -13,11 +13,13 @@ import logging import collections + from typing import List, Dict, Literal, Tuple, DefaultDict, NamedTuple import mm.image import mm.metamodel + class APageSize(NamedTuple): name: str width: int @@ -484,7 +486,24 @@ def _create_markdown(self, mmd_list: List[MemoryMapDiagram]) -> None: def _parse_args(cls): """Setup the command line interface""" parser = argparse.ArgumentParser( - description="""Generate a diagram showing how binary regions co-exist within memory.""" + formatter_class=argparse.RawTextHelpFormatter, + description= + """Tool for generating diagrams that show the mapping of regions in memory.""", + + epilog=""" +EXAMPLES +-------- +- Generate a map diagram called 'dram' that contains five regions called kernel, rootfs, dtb, uboot and uboot-scr where four of the five regions intersect/collide. + The default report output path is used. + + python3 -m mm.diagram kernel 0x10 0x50 rootfs 0x50 0x30 dtb 0x90 0x30 uboot 0xD0 0x50 uboot-scr 0x110 0x30 -l 0x3e8 -n dram + +- Using JSON many other options can be set. + Example json files can be found at https://cracked-machine.github.io/mmdiagram/examples.html + + python3 -m mm.diagram -f docs/example/example_two_maps.json + + """ ) parser.add_argument( "regions", @@ -553,15 +572,15 @@ def _validate_pargs(cls): root.setLevel(logging.DEBUG) # parse hex/int inputs if not Diagram.pargs.file and not Diagram.pargs.limit: - raise SystemExit("You must specify either: limit setting or JSON input file.") + raise SystemExit("Error: You must specify either: limit setting or JSON input file.") if not Diagram.pargs.file and Diagram.pargs.limit: if not Diagram.pargs.limit[:2] == "0x": - raise SystemExit(f"'limit' argument should be in hex format: {str(Diagram.pargs.limit)} = {hex(int(Diagram.pargs.limit))}") + raise SystemExit(f"Error: 'limit' argument should be in hex format: {str(Diagram.pargs.limit)} = {hex(int(Diagram.pargs.limit))}") if not Diagram.pargs.file and not Diagram.pargs.regions: raise SystemExit("You must provide either: region string or JSON input file.") if Diagram.pargs.threshold: if not Diagram.pargs.threshold[:2] == "0x": - raise SystemExit(f"'threshold' argument should be in hex format: {str(Diagram.pargs.threshold)} = {hex(int(Diagram.pargs.threshold))}") + raise SystemExit(f"Error: 'threshold' argument should be in hex format: {str(Diagram.pargs.threshold)} = {hex(int(Diagram.pargs.threshold))}") # make sure the output path is valid and parent dir exists if not pathlib.Path(Diagram.pargs.out).suffix == ".md": @@ -570,14 +589,14 @@ def _validate_pargs(cls): # check data point cardinality if len(sys.argv) == 1: - raise SystemExit("must pass in data points") + raise SystemExit("Error: You must pass in data points") if not Diagram.pargs.file: if len(Diagram.pargs.regions) % 3: - raise SystemExit("command line input data should be in multiples of three") + raise SystemExit("Error: Command line input data should be in multiples of three") else: json_file = pathlib.Path(Diagram.pargs.file).resolve() if not json_file.exists(): - raise SystemExit(f"File not found: {json_file}") + raise SystemExit(f"Error: File not found: {json_file}") @classmethod def _create_model(cls) -> mm.metamodel.Diagram: