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.
- declib/__init__.py +9 -0
- declib/__main__.py +190 -0
- declib/api/__init__.py +13 -0
- declib/api/artifact_dict.py +153 -0
- declib/api/artifact_lifter.py +161 -0
- declib/api/decompiler_client.py +1219 -0
- declib/api/decompiler_interface.py +1261 -0
- declib/api/decompiler_server.py +782 -0
- declib/api/server_registry.py +171 -0
- declib/api/type_definition_parser.py +201 -0
- declib/api/type_parser.py +409 -0
- declib/api/utils.py +31 -0
- declib/artifacts/__init__.py +93 -0
- declib/artifacts/artifact.py +311 -0
- declib/artifacts/comment.py +49 -0
- declib/artifacts/context.py +61 -0
- declib/artifacts/decompilation.py +35 -0
- declib/artifacts/enum.py +53 -0
- declib/artifacts/formatting.py +27 -0
- declib/artifacts/func.py +433 -0
- declib/artifacts/global_variable.py +31 -0
- declib/artifacts/patch.py +49 -0
- declib/artifacts/segment.py +37 -0
- declib/artifacts/stack_variable.py +50 -0
- declib/artifacts/struct.py +184 -0
- declib/artifacts/typedef.py +59 -0
- declib/cli/__init__.py +3 -0
- declib/cli/decompiler_cli.py +1487 -0
- declib/configuration.py +184 -0
- declib/decompiler_stubs/__init__.py +0 -0
- declib/decompiler_stubs/angr_declib/__init__.py +4 -0
- declib/decompiler_stubs/binja_declib/__init__.py +4 -0
- declib/decompiler_stubs/ida_declib.py +8 -0
- declib/decompilers/__init__.py +8 -0
- declib/decompilers/angr/__init__.py +11 -0
- declib/decompilers/angr/artifact_lifter.py +46 -0
- declib/decompilers/angr/compat.py +262 -0
- declib/decompilers/angr/interface.py +949 -0
- declib/decompilers/binja/__init__.py +0 -0
- declib/decompilers/binja/artifact_lifter.py +32 -0
- declib/decompilers/binja/hooks.py +201 -0
- declib/decompilers/binja/interface.py +795 -0
- declib/decompilers/ghidra/__init__.py +0 -0
- declib/decompilers/ghidra/artifact_lifter.py +60 -0
- declib/decompilers/ghidra/compat/__init__.py +0 -0
- declib/decompilers/ghidra/compat/headless.py +156 -0
- declib/decompilers/ghidra/compat/imports.py +78 -0
- declib/decompilers/ghidra/compat/state.py +54 -0
- declib/decompilers/ghidra/compat/transaction.py +30 -0
- declib/decompilers/ghidra/hooks.py +242 -0
- declib/decompilers/ghidra/interface.py +1433 -0
- declib/decompilers/ida/__init__.py +0 -0
- declib/decompilers/ida/artifact_lifter.py +51 -0
- declib/decompilers/ida/compat.py +2054 -0
- declib/decompilers/ida/hooks.py +700 -0
- declib/decompilers/ida/ida_ui.py +80 -0
- declib/decompilers/ida/interface.py +659 -0
- declib/logger.py +101 -0
- declib/plugin_installer.py +259 -0
- declib/skills/__init__.py +24 -0
- declib/skills/decompiler/SKILL.md +316 -0
- declib/ui/__init__.py +33 -0
- declib/ui/qt_objects.py +146 -0
- declib/ui/utils.py +115 -0
- declib/ui/version.py +14 -0
- declib-3.8.0.dist-info/METADATA +138 -0
- declib-3.8.0.dist-info/RECORD +71 -0
- declib-3.8.0.dist-info/WHEEL +5 -0
- declib-3.8.0.dist-info/entry_points.txt +3 -0
- declib-3.8.0.dist-info/licenses/LICENSE +24 -0
- 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