ocgraph 0.3.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. ocgraph/__init__.py +0 -0
  2. ocgraph/__main__.py +95 -0
  3. ocgraph/configuration/__init__.py +4 -0
  4. ocgraph/configuration/architecture/__init__.py +8 -0
  5. ocgraph/configuration/architecture/architecture.py +66 -0
  6. ocgraph/configuration/architecture/arm.py +52 -0
  7. ocgraph/configuration/architecture/msp430.py +48 -0
  8. ocgraph/configuration/architecture/ppc.py +698 -0
  9. ocgraph/configuration/architecture/sparc.py +100 -0
  10. ocgraph/configuration/architecture/x86.py +34 -0
  11. ocgraph/configuration/configuration.py +122 -0
  12. ocgraph/configuration/disassembler/__init__.py +10 -0
  13. ocgraph/configuration/disassembler/disassembler.py +148 -0
  14. ocgraph/configuration/disassembler/gdb_default.py +11 -0
  15. ocgraph/configuration/disassembler/objdump_arm.py +11 -0
  16. ocgraph/configuration/disassembler/objdump_msp430.py +27 -0
  17. ocgraph/configuration/disassembler/objdump_ppc.py +11 -0
  18. ocgraph/configuration/disassembler/objdump_sparc.py +11 -0
  19. ocgraph/configuration/disassembler/objdump_x86.py +11 -0
  20. ocgraph/configuration/logger.py +50 -0
  21. ocgraph/data/__init__.py +9 -0
  22. ocgraph/data/address.py +58 -0
  23. ocgraph/data/basic_block.py +37 -0
  24. ocgraph/data/encoding.py +34 -0
  25. ocgraph/data/function_header.py +23 -0
  26. ocgraph/data/instruction.py +102 -0
  27. ocgraph/data/jump_table.py +60 -0
  28. ocgraph/interface/__init__.py +5 -0
  29. ocgraph/interface/analyzer.py +220 -0
  30. ocgraph/interface/coverage_reader.py +70 -0
  31. ocgraph/interface/drawer.py +181 -0
  32. ocgraph-0.3.0.dist-info/LICENSES/GTDGmbH.md +24 -0
  33. ocgraph-0.3.0.dist-info/LICENSES/MauriMustonen.md +24 -0
  34. ocgraph-0.3.0.dist-info/METADATA +55 -0
  35. ocgraph-0.3.0.dist-info/RECORD +37 -0
  36. ocgraph-0.3.0.dist-info/WHEEL +4 -0
  37. ocgraph-0.3.0.dist-info/entry_points.txt +3 -0
@@ -0,0 +1,181 @@
1
+ # SPDX-License-Identifier: GTDGmbH
2
+ """Class for drawing the output."""
3
+
4
+ from __future__ import annotations
5
+
6
+ import tempfile
7
+ from typing import TYPE_CHECKING, Any
8
+
9
+ from graphviz import Digraph # type: ignore
10
+
11
+ from ocgraph.data import Coverage
12
+
13
+ if TYPE_CHECKING: # pragma: no cover
14
+ from ocgraph.configuration import OcGraphConfiguration
15
+ from ocgraph.data import BasicBlock
16
+
17
+ coverage_color = {
18
+ Coverage.MISS: "#f08080", # light coral
19
+ Coverage.LINE_TAKEN: "#90ee90", # light green
20
+ Coverage.JUMP_BOTH: "#90ee90", # light green
21
+ Coverage.JUMP_PASS: "#fdfd96", # pastel yellow
22
+ Coverage.JUMP_TAKEN: "#fdfd96", # pastel yellow
23
+ }
24
+
25
+
26
+ class Drawer:
27
+ """Drawer Class."""
28
+
29
+ def __init__(
30
+ self,
31
+ config: OcGraphConfiguration,
32
+ graph_options: dict[str, Any] | None = None,
33
+ ) -> None:
34
+ self.config = config
35
+ self.graph_option = graph_options if graph_options else {}
36
+
37
+ def set_graph_option(self, graph_options: dict[str, Any]) -> None:
38
+ """Set new graph options."""
39
+ self.graph_option = graph_options
40
+
41
+ @staticmethod
42
+ def _escape(text: str) -> str:
43
+ """
44
+ Escape used dot graph characters in given instruction so they will be
45
+ displayed correctly.
46
+ """
47
+ text = text.replace("&", "&")
48
+ text = text.replace("<", r"&lt;")
49
+ text = text.replace(">", r"&gt;")
50
+ return text.replace("\t", "&#9;")
51
+
52
+ def _create_label(
53
+ self,
54
+ basic_block: BasicBlock,
55
+ line_coverage: bool = False,
56
+ ) -> str:
57
+ """Create annotated graph label."""
58
+ label = ""
59
+ returns = set()
60
+
61
+ # start label
62
+ label += '< <TABLE BORDER="1" CELLBORDER="0" CELLSPACING="0" CELLPADDING="0"> \n'
63
+ # for each instruction in block
64
+ for instr in basic_block.instructions:
65
+ if not instr or not instr.address or not instr.opcode:
66
+ continue
67
+
68
+ bg_color = coverage_color[instr.coverage] if line_coverage else "white"
69
+ label += (
70
+ "<TR>"
71
+ f'<TD ALIGN="LEFT" COLSPAN="2" BGCOLOR="{bg_color}" >'
72
+ f"0x{instr.address.abs_addr:0>8x}: {instr.opcode:<10} "
73
+ f"{Drawer._escape(text=', '.join(instr.ops))}"
74
+ "</TD></TR>\n"
75
+ )
76
+ if self.config.architecture.is_sink(instr):
77
+ for return_addr in instr.returns:
78
+ if isinstance(return_addr, int):
79
+ returns.add(f"0x{return_addr:x}")
80
+
81
+ # add JUMP/NO JUMP cells with dot PORT navigation
82
+ cells = [basic_block.jump_edge, basic_block.no_jump_edge]
83
+ span = 3 - len(
84
+ [x for x in cells if x is not None],
85
+ ) # 3 - count of trues in cells
86
+
87
+ label = self._label_edges(label, basic_block, span, returns)
88
+ label += " </TABLE> >"
89
+ return label
90
+
91
+ def _label_edges(
92
+ self,
93
+ label: str,
94
+ basic_block: BasicBlock,
95
+ span: int,
96
+ returns: set[str],
97
+ ) -> str:
98
+ label += "<TR>"
99
+ if basic_block.no_jump_edge:
100
+ label += f'<TD BORDER="1" COLSPAN="{span}" PORT="pass">NO JUMP</TD>'
101
+ if basic_block.jump_edge:
102
+ label += f'<TD BORDER="1" COLSPAN="{span}" PORT="jump">JUMP</TD>'
103
+ if not basic_block.jump_edge and not basic_block.no_jump_edge:
104
+ label += (
105
+ f'<TD BORDER="1" COLSPAN="2">RETURN targets: '
106
+ f'{str(returns) if returns else "--"}</TD>'
107
+ )
108
+ label += "</TR>"
109
+ return label
110
+
111
+ def _create_cfg(
112
+ self,
113
+ name: str,
114
+ basic_blocks: dict[int, BasicBlock],
115
+ coverage: bool = False,
116
+ ) -> Digraph:
117
+ """Create a control flow graph."""
118
+ dot = Digraph(name=name, comment=name, engine="dot")
119
+ dot.attr("graph", label=name)
120
+ dot.attr("graph", fontname="Mono")
121
+ dot.attr("node", fontname="Mono")
122
+ dot.attr("edge", fontname="Mono")
123
+
124
+ basic_block_keys = []
125
+
126
+ # Create nodes in graph
127
+ for address, basic_block in basic_blocks.items():
128
+ key = str(address)
129
+ label = self._create_label(basic_block, coverage)
130
+ dot.node(name=key, label=label, shape="plaintext", **self.graph_option)
131
+ basic_block_keys.append(key)
132
+
133
+ # Create edges in graph
134
+ for basic_block in basic_blocks.values():
135
+ if basic_block.jump_edge:
136
+ key = str(basic_block.jump_edge)
137
+ if key not in basic_block_keys:
138
+ dot.node(
139
+ name=key,
140
+ label=hex(basic_block.jump_edge),
141
+ shape="plaintext",
142
+ **self.graph_option,
143
+ )
144
+ basic_block_keys.append(key)
145
+ dot.edge(f"{basic_block.key}:jump", str(basic_block.jump_edge))
146
+ if basic_block.no_jump_edge:
147
+ key = str(basic_block.no_jump_edge)
148
+ if key not in basic_block_keys:
149
+ dot.node(
150
+ name=key,
151
+ label=hex(basic_block.no_jump_edge),
152
+ shape="plaintext",
153
+ **self.graph_option,
154
+ )
155
+ basic_block_keys.append(key)
156
+ dot.edge(f"{basic_block.key}:pass", str(basic_block.no_jump_edge))
157
+ return dot
158
+
159
+ def view_cfg(self, name: str, basic_blocks: dict[int, BasicBlock]) -> None: # pragma: no cover
160
+ """View a function graph."""
161
+ dot = self._create_cfg(name, basic_blocks)
162
+ dot.format = "gv"
163
+ with tempfile.NamedTemporaryFile(mode="w+b", prefix=name) as filename:
164
+ dot.view(filename.name)
165
+
166
+ def draw_cfg(
167
+ self,
168
+ name: str,
169
+ basic_blocks: dict[int, BasicBlock],
170
+ output: str | None = None,
171
+ ) -> None:
172
+ """Draw a function graph."""
173
+ dot = self._create_cfg(name, basic_blocks, coverage=True)
174
+
175
+ filename = output if output else name
176
+ dot.format = "pdf"
177
+ dot.render(filename=filename, cleanup=True)
178
+ self.config.logger.info(f"Saved CFG to a file {filename}.{dot.format}")
179
+
180
+ dot.format = "gv"
181
+ dot.render(filename=filename, cleanup=True)
@@ -0,0 +1,24 @@
1
+ Valid-License-Identifier: GTDGmbH
2
+ License-Text:
3
+
4
+ Copyright (c) 2023 GTD GmbH. All rights reserved.
5
+
6
+ MIT License
7
+
8
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
9
+ this software and associated documentation files (the “Software”), to deal in
10
+ the Software without restriction, including without limitation the rights to
11
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
12
+ of the Software, and to permit persons to whom the Software is furnished to do
13
+ so, subject to the following conditions:
14
+
15
+ The above copyright notice and this permission notice shall be included in all
16
+ copies or substantial portions of the Software.
17
+
18
+ THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24
+ SOFTWARE.
@@ -0,0 +1,24 @@
1
+ Valid-License-Identifier: MauriMustonen
2
+ License-Text:
3
+
4
+ MIT License
5
+
6
+ Copyright (c) 2021 Mauri Mustonen
7
+
8
+ Permission is hereby granted, free of charge, to any person obtaining a copy
9
+ of this software and associated documentation files (the "Software"), to deal
10
+ in the Software without restriction, including without limitation the rights
11
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12
+ copies of the Software, and to permit persons to whom the Software is
13
+ furnished to do so, subject to the following conditions:
14
+
15
+ The above copyright notice and this permission notice shall be included in all
16
+ copies or substantial portions of the Software.
17
+
18
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24
+ SOFTWARE.
@@ -0,0 +1,55 @@
1
+ Metadata-Version: 2.3
2
+ Name: ocgraph
3
+ Version: 0.3.0
4
+ Summary: Tool to visualize object code as control flow graph
5
+ License: MIT
6
+ Keywords: Object Code,Control Flow Graph,ECSS Category A,asm2cfg,Coverage
7
+ Author: Mauri Mustonen
8
+ Author-email: kazooiebombchu@gmail.com
9
+ Maintainer: Christoph Weiss
10
+ Maintainer-email: christoph.weiss@gtd-gmbh.de
11
+ Requires-Python: >=3.9,<4.0
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.9
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Programming Language :: Python :: 3.11
18
+ Classifier: Programming Language :: Python :: 3.12
19
+ Classifier: Programming Language :: Python :: 3.13
20
+ Requires-Dist: graphviz (>=0.9,<0.10)
21
+ Project-URL: Documentation, https://gtd-gmbh.gitlab.io/beta-software/ocgraph
22
+ Project-URL: Forked from asm2cfg, https://github.com/Kazhuu/asm2cfg
23
+ Project-URL: Homepage, https://gtd-gmbh.de/cat-a
24
+ Project-URL: Repository, https://gitlab.com/gtd-gmbh/beta-software/ocgraph.git
25
+ Description-Content-Type: text/markdown
26
+
27
+ # Object Code Graph (ocgraph)
28
+
29
+ This repo contains *ocgraph*, (**Object Code Graph**), a tool to
30
+ read disassembler output and optionally corresponding coverage data to produce
31
+ control flow graphs including coverage analysis on assembler level.
32
+
33
+ The *ocgraph* source code implemented by GTD GmbH is forked from the asm2cfg
34
+ repository on [Github](https://github.com/Kazhuu/asm2cfg) and reworked to
35
+ function with several architectures and disassemblers.
36
+
37
+ The tool source code is subject to the MIT License as indicated by the headers
38
+ of the corresponding source code files.
39
+
40
+ [!WARNING]
41
+ > **WARNING**:
42
+ >
43
+ > **This tool is currently under development and in beta state It's not intended
44
+ > to be complete and using it is on your own risk.**
45
+
46
+ ## Documentation
47
+
48
+ Due to the lack of a full documentation, all previous information can be found
49
+ in separate *Markdown* files in the *doc* folder:
50
+
51
+ 1. [Installation](doc/1_Installation.md): Instructions to install the tool
52
+ 2. [How to Run](doc/2_HowToRun.md): Guideline to run the tool
53
+ 3. [Development](doc/3_Development.md): Information for Developer
54
+ 4. [Github asm2cfg](doc/4_Github.md): Original GitHub documentation
55
+
@@ -0,0 +1,37 @@
1
+ ocgraph/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ ocgraph/__main__.py,sha256=q2MEakTZdeeCC8QGyTQnk-fkh3i5PKZ0WMrzFK1Mflk,2716
3
+ ocgraph/configuration/__init__.py,sha256=caqDzvny40-Z3beWkcc4kHYI4qQo0zxTFVPQJidkdp4,173
4
+ ocgraph/configuration/architecture/__init__.py,sha256=grK51xPwyzfd5JKa98bY875dEsr3eafYyeJj4rWEYJU,379
5
+ ocgraph/configuration/architecture/architecture.py,sha256=wBhKwCJgYwjX6esu6tJz1Q6XpW20ZhcQ4ZA208Z0_hc,2351
6
+ ocgraph/configuration/architecture/arm.py,sha256=Oa-hpKwRv9kc8I5xE5Tdp0DWEBItGJktG0_aRteMsuw,1711
7
+ ocgraph/configuration/architecture/msp430.py,sha256=YEl4obWENoIzJyalfGjJTK1iGs4XIVMBey40hZo6i3g,1212
8
+ ocgraph/configuration/architecture/ppc.py,sha256=_ofKiWaSAl6s_XXg4BPPWiutnC9Ru6e0n4BHxP6tsho,9919
9
+ ocgraph/configuration/architecture/sparc.py,sha256=B8lqJYiWGuOtGS6vgzRZ4XdElSwSiRHauyJRgTL79dk,3198
10
+ ocgraph/configuration/architecture/x86.py,sha256=8fFcQhtOAO05CzUPDFWo8jfncjBNXNF2mEvIAal4OZ8,1067
11
+ ocgraph/configuration/configuration.py,sha256=YarXLhZibqTMuuiw7eT_naX08wXH90ykITx71mc_448,3477
12
+ ocgraph/configuration/disassembler/__init__.py,sha256=Djdux3AJ6zTPRhfwy88CPXsrMUVJWpyYRosR3sLx0NM,618
13
+ ocgraph/configuration/disassembler/disassembler.py,sha256=ApnKzgOI07V1-UD6BL2GmIGyXT5l6dLLq1O09d2Vghg,5367
14
+ ocgraph/configuration/disassembler/gdb_default.py,sha256=c1nsGsT2f3l8LADvIkreBV7etC8RxHyfSNTwy9dPxO4,255
15
+ ocgraph/configuration/disassembler/objdump_arm.py,sha256=z2WdDYcXeX3SKkT2BRk1o3IKwMOt0cnN4Z2O6fZG5uA,263
16
+ ocgraph/configuration/disassembler/objdump_msp430.py,sha256=RwKc2bGdzGomzstOcqmwEZwIfYQm-RaCMbemUlFZoZc,818
17
+ ocgraph/configuration/disassembler/objdump_ppc.py,sha256=JhOcYE2hFzUWWuf__Vqmr9k1U2ASn9QuJWNgcav4GoU,278
18
+ ocgraph/configuration/disassembler/objdump_sparc.py,sha256=aipSMiDXwzWyyT11OWhYGfIBOWPqdI02pb_vTETuy00,290
19
+ ocgraph/configuration/disassembler/objdump_x86.py,sha256=Mm_Of7gr9BPMjdSLJMnrREqGB6eTgslX0c2JKcjgmgQ,270
20
+ ocgraph/configuration/logger.py,sha256=RvcifAk83j1A0dr_ggTB-RjJbce-AfF9FqNt3SkRuOo,1450
21
+ ocgraph/data/__init__.py,sha256=K33Oe6IVtFkZBJCjB3oSvozWUxjggHvbdRjRPelXgLM,377
22
+ ocgraph/data/address.py,sha256=fjtZeXtb4u_tvPCrMADzQvDJP-1FQyb6ITLc4wEnh6o,1541
23
+ ocgraph/data/basic_block.py,sha256=ACGdp7UNSK2_zTqZSmsPIf6jxlYqNXT3C-zFQ3cueJI,1245
24
+ ocgraph/data/encoding.py,sha256=iTd9A4VgUS-Ay_t4P80raOcQlWkn2F6yw_IrUKXdhB4,709
25
+ ocgraph/data/function_header.py,sha256=eXla2drLjaU2h-KJ6Uj4Og7pEpl_xtbPVXTAurYycyQ,539
26
+ ocgraph/data/instruction.py,sha256=2y_j5AJ9PqOtuHit3Zc-Rv9epe1TlJRQMeWATstlZhY,3165
27
+ ocgraph/data/jump_table.py,sha256=kESmsyXegcoufseVBBJ2cTQOpOtcNItxKwfTQk8PEm4,2235
28
+ ocgraph/interface/__init__.py,sha256=LeG2MmjZ-lkTnzt42kVSxbntxC8xQ1WbQIF1luLoZbo,188
29
+ ocgraph/interface/analyzer.py,sha256=4zWLOnnVZ9uaIXB7FYCvAZr0-JhSRgwoYhfjnYU5Gho,8837
30
+ ocgraph/interface/coverage_reader.py,sha256=qBvAIV_L9Jvu5BSUqrJOeJ5AARl4loXRn1rHZNthB3w,2691
31
+ ocgraph/interface/drawer.py,sha256=B1a-4mIS15Wi5-1D0KJSajHqPcAVGts8ve3KCGfjyXE,6307
32
+ ocgraph-0.3.0.dist-info/LICENSES/GTDGmbH.md,sha256=Sh6tQQ93TslzOeB3P5pDOC7aO75_hT2REty8L9fZOlg,1144
33
+ ocgraph-0.3.0.dist-info/LICENSES/MauriMustonen.md,sha256=I9pTZ1awb__C_YoKDciaBx5yPRED5cQx5W2upVVm_n0,1126
34
+ ocgraph-0.3.0.dist-info/METADATA,sha256=0P27zNvzstlvhN4JavHBRLoj4GwbRLJMIyI-cUm5Oks,2265
35
+ ocgraph-0.3.0.dist-info/WHEEL,sha256=XbeZDeTWKc1w7CSIyre5aMDU_-PohRwTQceYnisIYYY,88
36
+ ocgraph-0.3.0.dist-info/entry_points.txt,sha256=4PfSLWgRL4CPVakqzZZVpJ223O9b0plfGdhv-OFUxEM,49
37
+ ocgraph-0.3.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: poetry-core 2.1.1
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,3 @@
1
+ [console_scripts]
2
+ ocgraph=ocgraph.__main__:main
3
+