Skip to content

Commit c55d791

Browse files
authored
Merge pull request #5 from elbiazo/dev
Dev
2 parents 8c57431 + 86c6d7b commit c55d791

File tree

4 files changed

+179
-127
lines changed

4 files changed

+179
-127
lines changed

Diff for: README.md

+3-12
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ Generates call tree
1010

1111
## Releases
1212

13-
* v0.0 -- Beta release
13+
* 1.0 -- Public Release
14+
* 0.0 -- Beta Release
1415

1516
## Minimum Version
1617

@@ -51,14 +52,4 @@ When working with really big binaries with alot of xrefs, you would want to chan
5152

5253
**Default Recursion Depth in Setting**
5354

54-
![](images/2022-02-09-16-59-03.png)
55-
56-
## Future Work:
57-
58-
- [ ] Ability to expand selected function
59-
- [x] Ability to expand all functions
60-
- [x] Setting and viewing depth of function recursion
61-
- [x] Move widget to side bar
62-
- [ ] Generating graph on current call tree
63-
- [ ] Refactor Code
64-
- [x] Documentation
55+
![](images/2022-02-09-16-59-03.png)

Diff for: calltree.py

+102-9
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,16 @@
33
QStandardItemModel,
44
QStandardItem,
55
)
6+
from PySide6.QtCore import QSize, Qt
67
from PySide6.QtWidgets import QTreeView
8+
from PySide6.QtWidgets import (
9+
QVBoxLayout,
10+
QHBoxLayout,
11+
QPushButton,
12+
QLineEdit,
13+
QSpinBox,
14+
QTextEdit,
15+
)
716

817

918
class BNFuncItem(QStandardItem):
@@ -13,25 +22,109 @@ def __init__(self, func):
1322
self.setText(func.name)
1423

1524

16-
class CallTreeWidget:
17-
def __init__(self, label_name, depth):
18-
self.treeview = QTreeView()
19-
self.model = QStandardItemModel()
20-
self.proxy_model = QSortFilterProxyModel(self.treeview)
25+
class CurrentFunctionLayout(QHBoxLayout):
26+
def __init__(self):
27+
super().__init__()
28+
self.cur_func_text = QTextEdit()
29+
self.cur_func_text.setReadOnly(True)
30+
self.cur_func_text.setMaximumHeight(40)
31+
self.cur_func_text.setAlignment(Qt.AlignLeft | Qt.AlignTop)
32+
self.cur_func_text.setLineWrapMode(QTextEdit.NoWrap)
33+
super().addWidget(self.cur_func_text)
34+
35+
36+
# Layout with search bar and expand/collapse buttons
37+
# Takes CallTreeLayout as a parameter
38+
class CallTreeUtilLayout(QHBoxLayout):
39+
def __init__(self, calltree: object):
40+
super().__init__()
41+
self.calltree = calltree
42+
btn_size = QSize(25, 25)
43+
self.expand_all_button = QPushButton("E")
44+
self.expand_all_button.setFixedSize(btn_size)
45+
self.expand_all_button.clicked.connect(self.calltree.expand_all)
46+
47+
self.collapse_all_button = QPushButton("C")
48+
self.collapse_all_button.setFixedSize(btn_size)
49+
self.collapse_all_button.clicked.connect(self.calltree.collapse_all)
50+
51+
self.func_filter = QLineEdit()
52+
self.func_filter.textChanged.connect(self.calltree.onTextChanged)
53+
54+
self.spinbox = QSpinBox()
55+
self.spinbox.valueChanged.connect(self.spinbox_changed)
56+
self.spinbox.setValue(self.calltree.func_depth)
57+
super().addWidget(self.func_filter)
58+
super().addWidget(self.expand_all_button)
59+
super().addWidget(self.collapse_all_button)
60+
super().addWidget(self.spinbox)
61+
62+
def spinbox_changed(self):
63+
self.calltree.func_depth = self.spinbox.value()
64+
if self.calltree.cur_func is not None:
65+
self.calltree.update_widget(self.calltree.cur_func)
66+
67+
68+
class CallTreeLayout(QVBoxLayout):
69+
def __init__(self, label_name: str, depth: int, is_caller: bool):
70+
super().__init__()
71+
self._cur_func = None
72+
self._is_caller = is_caller
73+
# Creates treeview for all the function calls
74+
self._treeview = QTreeView()
75+
self._model = QStandardItemModel()
76+
self._proxy_model = QSortFilterProxyModel(self.treeview)
2177
self.proxy_model.setSourceModel(self.model)
2278

2379
self.treeview.setModel(self.proxy_model)
80+
81+
# Clicking function on treeview will take you to the function
2482
self.treeview.doubleClicked.connect(self.goto_func)
2583
self._func_depth = depth
2684
self._binary_view = None
27-
self.label_name = label_name
85+
self._label_name = label_name
2886
self.set_label(self.label_name)
87+
super().addWidget(self.treeview)
88+
self.util = CallTreeUtilLayout(self)
89+
super().addLayout(self.util)
2990

3091
def onTextChanged(self, text):
3192
self.proxy_model.setRecursiveFilteringEnabled(True)
3293
self.proxy_model.setFilterRegularExpression(text)
3394
self.expand_all()
3495

96+
@property
97+
def proxy_model(self):
98+
return self._proxy_model
99+
100+
@property
101+
def label_name(self):
102+
return self._label_name
103+
104+
@property
105+
def cur_func(self):
106+
return self._cur_func
107+
108+
@cur_func.setter
109+
def cur_func(self, cur_func):
110+
self._cur_func = cur_func
111+
112+
@property
113+
def is_caller(self):
114+
return self._is_caller
115+
116+
@property
117+
def treeview(self):
118+
return self._treeview
119+
120+
@property
121+
def func_depth(self):
122+
return self._func_depth
123+
124+
@property
125+
def model(self):
126+
return self._model
127+
35128
@property
36129
def binary_view(self):
37130
return self._binary_view
@@ -79,12 +172,12 @@ def set_func_calls(self, cur_func, cur_std_item, is_caller: bool, depth=0):
79172
cur_func_call, new_std_item, is_caller, depth + 1
80173
)
81174

82-
def update_widget(self, cur_func, is_caller):
175+
def update_widget(self, cur_func):
83176
# Clear previous calls
84177
self.clear()
85178
call_root_node = self.model.invisibleRootItem()
86179

87-
if is_caller:
180+
if self.is_caller:
88181
cur_func_calls = list(set(cur_func.callers))
89182
else:
90183
cur_func_calls = list(set(cur_func.callees))
@@ -97,7 +190,7 @@ def update_widget(self, cur_func, is_caller):
97190
root_std_items.append(BNFuncItem(cur_func_call))
98191
cur_std_item = root_std_items[-1]
99192
if cur_func != cur_func_call:
100-
self.set_func_calls(cur_func_call, cur_std_item, is_caller)
193+
self.set_func_calls(cur_func_call, cur_std_item, self.is_caller)
101194

102195
call_root_node.appendRows(root_std_items)
103196
self.expand_all()

Diff for: icon.png

21.2 KB
Loading

0 commit comments

Comments
 (0)