declib 3.8.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 (71) hide show
  1. declib/__init__.py +9 -0
  2. declib/__main__.py +190 -0
  3. declib/api/__init__.py +13 -0
  4. declib/api/artifact_dict.py +153 -0
  5. declib/api/artifact_lifter.py +161 -0
  6. declib/api/decompiler_client.py +1219 -0
  7. declib/api/decompiler_interface.py +1261 -0
  8. declib/api/decompiler_server.py +782 -0
  9. declib/api/server_registry.py +171 -0
  10. declib/api/type_definition_parser.py +201 -0
  11. declib/api/type_parser.py +409 -0
  12. declib/api/utils.py +31 -0
  13. declib/artifacts/__init__.py +93 -0
  14. declib/artifacts/artifact.py +311 -0
  15. declib/artifacts/comment.py +49 -0
  16. declib/artifacts/context.py +61 -0
  17. declib/artifacts/decompilation.py +35 -0
  18. declib/artifacts/enum.py +53 -0
  19. declib/artifacts/formatting.py +27 -0
  20. declib/artifacts/func.py +433 -0
  21. declib/artifacts/global_variable.py +31 -0
  22. declib/artifacts/patch.py +49 -0
  23. declib/artifacts/segment.py +37 -0
  24. declib/artifacts/stack_variable.py +50 -0
  25. declib/artifacts/struct.py +184 -0
  26. declib/artifacts/typedef.py +59 -0
  27. declib/cli/__init__.py +3 -0
  28. declib/cli/decompiler_cli.py +1487 -0
  29. declib/configuration.py +184 -0
  30. declib/decompiler_stubs/__init__.py +0 -0
  31. declib/decompiler_stubs/angr_declib/__init__.py +4 -0
  32. declib/decompiler_stubs/binja_declib/__init__.py +4 -0
  33. declib/decompiler_stubs/ida_declib.py +8 -0
  34. declib/decompilers/__init__.py +8 -0
  35. declib/decompilers/angr/__init__.py +11 -0
  36. declib/decompilers/angr/artifact_lifter.py +46 -0
  37. declib/decompilers/angr/compat.py +262 -0
  38. declib/decompilers/angr/interface.py +949 -0
  39. declib/decompilers/binja/__init__.py +0 -0
  40. declib/decompilers/binja/artifact_lifter.py +32 -0
  41. declib/decompilers/binja/hooks.py +201 -0
  42. declib/decompilers/binja/interface.py +795 -0
  43. declib/decompilers/ghidra/__init__.py +0 -0
  44. declib/decompilers/ghidra/artifact_lifter.py +60 -0
  45. declib/decompilers/ghidra/compat/__init__.py +0 -0
  46. declib/decompilers/ghidra/compat/headless.py +156 -0
  47. declib/decompilers/ghidra/compat/imports.py +78 -0
  48. declib/decompilers/ghidra/compat/state.py +54 -0
  49. declib/decompilers/ghidra/compat/transaction.py +30 -0
  50. declib/decompilers/ghidra/hooks.py +242 -0
  51. declib/decompilers/ghidra/interface.py +1433 -0
  52. declib/decompilers/ida/__init__.py +0 -0
  53. declib/decompilers/ida/artifact_lifter.py +51 -0
  54. declib/decompilers/ida/compat.py +2054 -0
  55. declib/decompilers/ida/hooks.py +700 -0
  56. declib/decompilers/ida/ida_ui.py +80 -0
  57. declib/decompilers/ida/interface.py +659 -0
  58. declib/logger.py +101 -0
  59. declib/plugin_installer.py +259 -0
  60. declib/skills/__init__.py +24 -0
  61. declib/skills/decompiler/SKILL.md +316 -0
  62. declib/ui/__init__.py +33 -0
  63. declib/ui/qt_objects.py +146 -0
  64. declib/ui/utils.py +115 -0
  65. declib/ui/version.py +14 -0
  66. declib-3.8.0.dist-info/METADATA +138 -0
  67. declib-3.8.0.dist-info/RECORD +71 -0
  68. declib-3.8.0.dist-info/WHEEL +5 -0
  69. declib-3.8.0.dist-info/entry_points.txt +3 -0
  70. declib-3.8.0.dist-info/licenses/LICENSE +24 -0
  71. declib-3.8.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,184 @@
1
+ from typing import Dict, List, Optional
2
+
3
+ import toml
4
+
5
+ from .artifact import Artifact
6
+ from . import TomlHexEncoder
7
+
8
+ import logging
9
+ l = logging.getLogger(name=__name__)
10
+
11
+
12
+ class StructMember(Artifact):
13
+ """
14
+ Describes a struct member that corresponds to a struct.
15
+ Offset is the byte offset of the member from the start of the struct.
16
+ """
17
+
18
+ __slots__ = Artifact.__slots__ + (
19
+ "name",
20
+ "offset",
21
+ "type",
22
+ "size",
23
+ )
24
+
25
+ def __init__(
26
+ self,
27
+ name: str = None,
28
+ offset: int = None,
29
+ type_: Optional[str] = None,
30
+ size: int = None,
31
+ **kwargs
32
+ ):
33
+ super().__init__(**kwargs)
34
+ self.name: str = name
35
+ self.offset: int = offset
36
+ self.type: str = type_
37
+ self.size: int = size
38
+
39
+ def __str__(self):
40
+ return f"<StructMember: {self.type} {self.name}; @{hex(self.offset)}>"
41
+
42
+
43
+ class Struct(Artifact):
44
+ """
45
+ Describes a struct.
46
+ All members are stored by their byte offset from the start of the struct.
47
+ """
48
+
49
+ __slots__ = Artifact.__slots__ + (
50
+ "name",
51
+ "size",
52
+ "members",
53
+ )
54
+
55
+ def __init__(
56
+ self,
57
+ name: str = None,
58
+ size: int = None,
59
+ members: Dict[int, StructMember] = None,
60
+ **kwargs
61
+ ):
62
+ super().__init__(**kwargs)
63
+ self.name = name
64
+ self.size = size or 0
65
+ self.members: Dict[int, StructMember] = members or {}
66
+
67
+ def __str__(self):
68
+ scope_str = f" scope={self.scope}" if self.scope else ""
69
+ return f"<Struct: {self.name} membs={len(self.members)}{scope_str} ({hex(self.size)})>"
70
+
71
+ def __getstate__(self):
72
+ data_dict = super().__getstate__()
73
+ data_dict["members"] = {
74
+ hex(offset): member.__getstate__() for offset, member in self.members.items()
75
+ }
76
+
77
+ return data_dict
78
+
79
+ def __setstate__(self, state):
80
+ # XXX: this is a backport of the old state format. Remove this after a few releases.
81
+ if "metadata" in state:
82
+ metadata: Dict = state.pop("metadata")
83
+ metadata.update(state)
84
+ state = metadata
85
+
86
+ # Pop nested object data and reconstruct in local variable
87
+ members_dat = state.pop("members", None)
88
+ members = {}
89
+ if members_dat:
90
+ for off, member in members_dat.items():
91
+ sm = StructMember()
92
+ sm.__setstate__(member)
93
+ members[int(off, 0)] = sm
94
+
95
+ # Put reconstructed objects back in state
96
+ state["members"] = members
97
+
98
+ # Let super set all attributes at once
99
+ super().__setstate__(state)
100
+
101
+ def add_struct_member(self, mname, moff, mtype, size):
102
+ self.members[moff] = StructMember(mname, moff, mtype, size)
103
+
104
+ def append_struct_member(self, mname, mtype, size):
105
+ # first, find the next available offset
106
+ next_offset = 0
107
+ for off in self.members.keys():
108
+ if off >= next_offset:
109
+ next_offset = off + self.members[off].size
110
+ self.members[next_offset] = StructMember(mname, next_offset, mtype, size)
111
+
112
+ def diff(self, other, **kwargs) -> Dict:
113
+ diff_dict = {}
114
+ if not isinstance(other, Struct):
115
+ return diff_dict
116
+
117
+ for k in ["name", "size"]:
118
+ if getattr(self, k) == getattr(other, k):
119
+ continue
120
+
121
+ diff_dict[k] = {
122
+ "before": getattr(self, k),
123
+ "after": getattr(other, k)
124
+ }
125
+
126
+ # struct members
127
+ diff_dict["members"] = {}
128
+ for off, member in self.members.items():
129
+ try:
130
+ other_mem = other.members[off]
131
+ except KeyError:
132
+ other_mem = None
133
+
134
+ diff_dict["members"][off] = member.diff(other_mem)
135
+
136
+ for off, other_mem in other.members.items():
137
+ if off in diff_dict["members"]:
138
+ continue
139
+
140
+ diff_dict["members"][off] = self.invert_diff(other_mem.diff(None))
141
+
142
+ return diff_dict
143
+
144
+ def nonconflict_merge(self, struct2: "Struct", **kwargs) -> "Struct":
145
+ struct1: "Struct" = self.copy()
146
+ if not struct2 or struct1 == struct2:
147
+ return struct1
148
+
149
+ struct_diff = struct1.diff(struct2)
150
+ merge_struct = struct1
151
+
152
+ members_diff = struct_diff["members"]
153
+ for off, mem in struct2.members.items():
154
+ # no difference
155
+ if off not in members_diff:
156
+ continue
157
+
158
+ mem_diff = members_diff[off]
159
+
160
+ # struct member is newly created
161
+ if "before" in mem_diff and mem_diff["before"] is None:
162
+ # check for overlap
163
+ new_mem_size = mem.size
164
+ new_mem_offset = mem.offset
165
+
166
+ for off_check in range(new_mem_offset, new_mem_offset + new_mem_size):
167
+ if off_check in merge_struct.members:
168
+ break
169
+ else:
170
+ merge_struct.members[off] = mem.copy()
171
+
172
+ continue
173
+
174
+ # member differs
175
+ merge_mem = merge_struct.members.get(off, None)
176
+ if not merge_mem:
177
+ merge_mem = mem
178
+
179
+ merge_mem = StructMember.nonconflict_merge(merge_mem, mem)
180
+ merge_struct.members[off] = merge_mem
181
+
182
+ # compute the new size
183
+ merge_struct.size = sum(mem.size for mem in merge_struct.members.values())
184
+ return merge_struct
@@ -0,0 +1,59 @@
1
+ from typing import Optional
2
+
3
+ from .artifact import Artifact
4
+
5
+
6
+ class Typedef(Artifact):
7
+ """
8
+ Describe a typedef. As an example:
9
+ typedef struct MyStruct {
10
+ int a;
11
+ int b;
12
+ } my_struct_t;
13
+
14
+ name="my_struct_t"
15
+ type="MyStruct"
16
+
17
+ Another example:
18
+ typedef int my_int_t;
19
+
20
+ name="my_int_t"
21
+ type="int"
22
+ """
23
+
24
+ __slots__ = Artifact.__slots__ + (
25
+ "name",
26
+ "type",
27
+ )
28
+
29
+ def __init__(
30
+ self,
31
+ name: str = None,
32
+ type_: Optional[str] = None,
33
+ **kwargs,
34
+ ):
35
+ super().__init__(**kwargs)
36
+ self.name: str = name
37
+ self.type: str = type_
38
+
39
+ def __str__(self):
40
+ scope_str = f" scope={self.scope}" if self.scope else ""
41
+ return f"<TypeDef: {self.name}={self.type}{scope_str}>"
42
+
43
+ def nonconflict_merge(self, typedef2: "Typedef", **kwargs):
44
+ typedef1: Typedef = self.copy()
45
+ if not typedef2 or typedef1 == typedef2:
46
+ return typedef1.copy()
47
+
48
+ master_state = kwargs.get("master_state", None)
49
+ local_names = {typedef1.name}
50
+ if master_state:
51
+ for _, typedef in master_state.get_typedefs().items():
52
+ local_names.add(typedef.name)
53
+ else:
54
+ local_names = {typedef1.name}
55
+
56
+ if typedef2.name not in local_names:
57
+ typedef1.name = typedef2.name
58
+ typedef1.type = typedef2.type
59
+ return typedef1
declib/cli/__init__.py ADDED
@@ -0,0 +1,3 @@
1
+ from declib.cli.decompiler_cli import main
2
+
3
+ __all__ = ["main"]