hilda 0.2.0__py3-none-any.whl → 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.
- hilda/hilda_client.py +19 -4
- hilda/lldb_entrypoint.py +3 -1
- hilda/snippets/xpc.py +9 -0
- hilda/ui/colors.json +13 -0
- hilda/ui/ui_manager.py +74 -0
- hilda/ui/views.py +217 -0
- {hilda-0.2.0.dist-info → hilda-0.3.0.dist-info}/METADATA +62 -2
- {hilda-0.2.0.dist-info → hilda-0.3.0.dist-info}/RECORD +12 -9
- {hilda-0.2.0.dist-info → hilda-0.3.0.dist-info}/WHEEL +1 -1
- {hilda-0.2.0.dist-info → hilda-0.3.0.dist-info}/LICENSE +0 -0
- {hilda-0.2.0.dist-info → hilda-0.3.0.dist-info}/entry_points.txt +0 -0
- {hilda-0.2.0.dist-info → hilda-0.3.0.dist-info}/top_level.txt +0 -0
hilda/hilda_client.py
CHANGED
|
@@ -9,12 +9,13 @@ import os
|
|
|
9
9
|
import pickle
|
|
10
10
|
import textwrap
|
|
11
11
|
import time
|
|
12
|
+
import typing
|
|
12
13
|
from collections import namedtuple
|
|
13
14
|
from contextlib import contextmanager, suppress
|
|
14
15
|
from datetime import datetime, timezone
|
|
15
16
|
from functools import cached_property, partial
|
|
16
17
|
from pathlib import Path
|
|
17
|
-
from typing import Union
|
|
18
|
+
from typing import List, Optional, Union
|
|
18
19
|
|
|
19
20
|
import docstring_parser
|
|
20
21
|
import hexdump
|
|
@@ -40,6 +41,7 @@ from hilda.registers import Registers
|
|
|
40
41
|
from hilda.snippets.mach import CFRunLoopServiceMachPort_hooks
|
|
41
42
|
from hilda.symbol import Symbol
|
|
42
43
|
from hilda.symbols_jar import SymbolsJar
|
|
44
|
+
from hilda.ui.ui_manager import UiManager
|
|
43
45
|
|
|
44
46
|
IsaMagic = namedtuple('IsaMagic', 'mask value')
|
|
45
47
|
ISA_MAGICS = [
|
|
@@ -81,6 +83,7 @@ class HildaClient(metaclass=CommandsMeta):
|
|
|
81
83
|
self.captured_objects = {}
|
|
82
84
|
self.registers = Registers(self)
|
|
83
85
|
self.arch = self.target.GetTriple().split('-')[0]
|
|
86
|
+
self.ui_manager = UiManager(self)
|
|
84
87
|
# should unwind the stack on errors. change this to False in order to debug self-made calls
|
|
85
88
|
# within hilda
|
|
86
89
|
self._evaluation_unwind_on_error = True
|
|
@@ -120,16 +123,22 @@ class HildaClient(metaclass=CommandsMeta):
|
|
|
120
123
|
return {int(k): v for k, v in result.items()}
|
|
121
124
|
|
|
122
125
|
@command()
|
|
123
|
-
def bt(self):
|
|
126
|
+
def bt(self, should_print=True, depth: Optional[int] = None) -> List:
|
|
124
127
|
""" Print an improved backtrace. """
|
|
128
|
+
backtrace = []
|
|
125
129
|
for i, frame in enumerate(self.thread.frames):
|
|
130
|
+
if i == depth:
|
|
131
|
+
break
|
|
126
132
|
row = ''
|
|
127
133
|
row += html_to_ansi(f'<span style="color: cyan">0x{frame.addr.GetFileAddress():x}</span> ')
|
|
128
134
|
row += str(frame)
|
|
129
135
|
if i == 0:
|
|
130
136
|
# first line
|
|
131
137
|
row += ' 👈'
|
|
132
|
-
|
|
138
|
+
backtrace.append([f'0x{frame.addr.file_addr:016x}', frame])
|
|
139
|
+
if should_print:
|
|
140
|
+
print(row)
|
|
141
|
+
return backtrace
|
|
133
142
|
|
|
134
143
|
@command()
|
|
135
144
|
def disable_jetsam_memory_checks(self):
|
|
@@ -514,12 +523,16 @@ class HildaClient(metaclass=CommandsMeta):
|
|
|
514
523
|
""" Step into current instruction. """
|
|
515
524
|
with self.sync_mode():
|
|
516
525
|
self.thread.StepInto()
|
|
526
|
+
if self.ui_manager.active:
|
|
527
|
+
self.ui_manager.show()
|
|
517
528
|
|
|
518
529
|
@command()
|
|
519
530
|
def step_over(self):
|
|
520
531
|
""" Step over current instruction. """
|
|
521
532
|
with self.sync_mode():
|
|
522
533
|
self.thread.StepOver()
|
|
534
|
+
if self.ui_manager.active:
|
|
535
|
+
self.ui_manager.show()
|
|
523
536
|
|
|
524
537
|
@command()
|
|
525
538
|
def remove_all_hilda_breakpoints(self, remove_forced=False):
|
|
@@ -1008,7 +1021,7 @@ class HildaClient(metaclass=CommandsMeta):
|
|
|
1008
1021
|
|
|
1009
1022
|
return value
|
|
1010
1023
|
|
|
1011
|
-
def interactive(self):
|
|
1024
|
+
def interactive(self, additional_namespace: typing.Mapping = None):
|
|
1012
1025
|
""" Start an interactive Hilda shell """
|
|
1013
1026
|
if not self._dynamic_env_loaded:
|
|
1014
1027
|
self.init_dynamic_environment()
|
|
@@ -1024,6 +1037,8 @@ class HildaClient(metaclass=CommandsMeta):
|
|
|
1024
1037
|
]
|
|
1025
1038
|
namespace = globals()
|
|
1026
1039
|
namespace.update(locals())
|
|
1040
|
+
if additional_namespace is not None:
|
|
1041
|
+
namespace.update(additional_namespace)
|
|
1027
1042
|
|
|
1028
1043
|
IPython.start_ipython(config=c, user_ns=namespace)
|
|
1029
1044
|
|
hilda/lldb_entrypoint.py
CHANGED
|
@@ -15,7 +15,9 @@ lldb.hilda_client = None
|
|
|
15
15
|
def hilda(debugger, command, result, internal_dict):
|
|
16
16
|
if lldb.hilda_client is None:
|
|
17
17
|
lldb.hilda_client = HildaClient(debugger)
|
|
18
|
-
|
|
18
|
+
|
|
19
|
+
additional_namespace = {'ui': lldb.hilda_client.ui_manager}
|
|
20
|
+
lldb.hilda_client.interactive(additional_namespace=additional_namespace)
|
|
19
21
|
|
|
20
22
|
|
|
21
23
|
def __lldb_init_module(debugger, internal_dict):
|
hilda/snippets/xpc.py
CHANGED
|
@@ -54,6 +54,15 @@ def from_xpc_object(address: int):
|
|
|
54
54
|
return lldb.hilda_client.from_ns(f'_CFXPCCreateCFObjectFromXPCObject({address})')
|
|
55
55
|
|
|
56
56
|
|
|
57
|
+
def disable_transaction_exit():
|
|
58
|
+
"""
|
|
59
|
+
xpc_transaction_exit_clean will kill the process when transaction is done.
|
|
60
|
+
By patching this function the process will stay alive.
|
|
61
|
+
"""
|
|
62
|
+
hilda = lldb.hilda_client
|
|
63
|
+
hilda.symbols.xpc_transaction_exit_clean.poke_text('ret')
|
|
64
|
+
|
|
65
|
+
|
|
57
66
|
def to_xpc_object(obj: object):
|
|
58
67
|
"""
|
|
59
68
|
Convert python object to XPC object.
|
hilda/ui/colors.json
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
{
|
|
2
|
+
"title": "green",
|
|
3
|
+
"address": "bright_blue",
|
|
4
|
+
"regs_title": "green",
|
|
5
|
+
"regs_name": "cyan",
|
|
6
|
+
"regs_value": "white",
|
|
7
|
+
"mnemonic": "white",
|
|
8
|
+
"operands": "white",
|
|
9
|
+
"basename": "yellow",
|
|
10
|
+
"stack_offset": "white",
|
|
11
|
+
"stack_data": "white",
|
|
12
|
+
"diff": "red"
|
|
13
|
+
}
|
hilda/ui/ui_manager.py
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import json
|
|
2
|
+
from collections import OrderedDict
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
|
|
5
|
+
from hilda.ui.views import BackTraceView, DisassemblyView, RegistersView, StackView
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class DotDict(OrderedDict):
|
|
9
|
+
""" Extends `OrderedDict` to access items using dot """
|
|
10
|
+
__slots__ = ["__recursion_lock__"]
|
|
11
|
+
|
|
12
|
+
def __getattr__(self, name):
|
|
13
|
+
try:
|
|
14
|
+
if name in self.__slots__:
|
|
15
|
+
return object.__getattribute__(self, name)
|
|
16
|
+
else:
|
|
17
|
+
return self[name]
|
|
18
|
+
except KeyError:
|
|
19
|
+
raise AttributeError(name)
|
|
20
|
+
|
|
21
|
+
def __setattr__(self, name, value):
|
|
22
|
+
try:
|
|
23
|
+
if name in self.__slots__:
|
|
24
|
+
return object.__setattr__(self, name, value)
|
|
25
|
+
else:
|
|
26
|
+
self[name] = value
|
|
27
|
+
except KeyError:
|
|
28
|
+
raise AttributeError(name)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class ColorScheme(DotDict):
|
|
32
|
+
def __init__(self, scheme: Path):
|
|
33
|
+
with scheme.open('r') as f:
|
|
34
|
+
data = json.load(f)
|
|
35
|
+
super().__init__(data)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class ViewsManager(DotDict):
|
|
39
|
+
pass
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class UiManager:
|
|
43
|
+
"""
|
|
44
|
+
Manages Hilda's UI.
|
|
45
|
+
|
|
46
|
+
- New views can be added to `ViewManager` (Must be inherent `Views`)
|
|
47
|
+
- Colors can be changed from terminal (Setting `ui_manager.color.title = 'green'` or be modifying `colors.json`)
|
|
48
|
+
- Views can be disabled from terminal (Setting `ui_manager.color.title=False`)
|
|
49
|
+
"""
|
|
50
|
+
|
|
51
|
+
def __init__(self, hilda_client, scheme_file=Path(__file__).parent / 'colors.json',
|
|
52
|
+
active: bool = True):
|
|
53
|
+
"""
|
|
54
|
+
:param hilda_client: hilda.hilda_client.HildaClient
|
|
55
|
+
:param scheme_file: pathlib.Path
|
|
56
|
+
:param active: bool
|
|
57
|
+
"""
|
|
58
|
+
self.colors = ColorScheme(scheme_file)
|
|
59
|
+
self.views = ViewsManager({
|
|
60
|
+
'registers': RegistersView(hilda_client, self.colors),
|
|
61
|
+
'disassembly': DisassemblyView(hilda_client, self.colors),
|
|
62
|
+
'stack': StackView(hilda_client, self.colors),
|
|
63
|
+
'backtrace': BackTraceView(hilda_client, self.colors)
|
|
64
|
+
})
|
|
65
|
+
self.active = active
|
|
66
|
+
|
|
67
|
+
def show(self, *args) -> None:
|
|
68
|
+
fmt_parts = []
|
|
69
|
+
|
|
70
|
+
for view in self.views.values():
|
|
71
|
+
if view.active is False:
|
|
72
|
+
continue
|
|
73
|
+
fmt_parts.append(str(view))
|
|
74
|
+
print('\n'.join(fmt_parts))
|
hilda/ui/views.py
ADDED
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
import shutil
|
|
2
|
+
from abc import abstractmethod
|
|
3
|
+
from typing import List, Mapping
|
|
4
|
+
|
|
5
|
+
from click import style
|
|
6
|
+
from lldb import SBAddress
|
|
7
|
+
from tabulate import tabulate
|
|
8
|
+
|
|
9
|
+
WORD_SIZE = 8
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def dict_diff(d1: Mapping, d2: Mapping) -> List[str]:
|
|
13
|
+
""" Returns a list of keys whose values have changed """
|
|
14
|
+
changed_keys = []
|
|
15
|
+
if d1 is None or d2 is None:
|
|
16
|
+
return changed_keys
|
|
17
|
+
for k, v in d1.items():
|
|
18
|
+
if k in d2 and d2[k] != v:
|
|
19
|
+
changed_keys.append(k)
|
|
20
|
+
return changed_keys
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class View:
|
|
24
|
+
""" Base class of view"""
|
|
25
|
+
|
|
26
|
+
def __init__(self, hilda_client, title, color_scheme):
|
|
27
|
+
"""
|
|
28
|
+
:param hilda_client: hilda.hilda_client.HildaClient
|
|
29
|
+
:param title: str
|
|
30
|
+
:param color_scheme: hilda.ui.ui_manager.ColorScheme
|
|
31
|
+
"""
|
|
32
|
+
self.title = title
|
|
33
|
+
self.hilda = hilda_client
|
|
34
|
+
self.active = True
|
|
35
|
+
self.color_scheme = color_scheme
|
|
36
|
+
|
|
37
|
+
@abstractmethod
|
|
38
|
+
def __str__(self) -> str:
|
|
39
|
+
return self._format_title()
|
|
40
|
+
|
|
41
|
+
def _format_title(self) -> str:
|
|
42
|
+
terminal_size = shutil.get_terminal_size()
|
|
43
|
+
fmt = style(self.title.center(terminal_size.columns, '─'), fg=self.color_scheme.title)
|
|
44
|
+
fmt += '\n'
|
|
45
|
+
return fmt
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
class StackView(View):
|
|
49
|
+
""" Implements stack view """
|
|
50
|
+
DEFAULT_STACK_DEPTH = 10
|
|
51
|
+
|
|
52
|
+
def __init__(self, hilda_client, color_scheme, depth=DEFAULT_STACK_DEPTH):
|
|
53
|
+
"""
|
|
54
|
+
:param hilda_client: hilda.hilda_client.HildaClient
|
|
55
|
+
:param depth: int
|
|
56
|
+
:param color_scheme: hilda.ui.ui_manager.ColorScheme
|
|
57
|
+
|
|
58
|
+
`prev` saves the last stack stats inorder to perform diff check.
|
|
59
|
+
"""
|
|
60
|
+
super().__init__(hilda_client, 'Stack', color_scheme)
|
|
61
|
+
self.depth = depth
|
|
62
|
+
self.prev: Mapping[int, str] = None
|
|
63
|
+
|
|
64
|
+
def __str__(self) -> str:
|
|
65
|
+
""" Format stack view for printing """
|
|
66
|
+
stack_mapping = self._create_mapping()
|
|
67
|
+
diff_in_keys = dict_diff(stack_mapping, self.prev)
|
|
68
|
+
self.prev = stack_mapping.copy()
|
|
69
|
+
fmt_parts = []
|
|
70
|
+
offset = 0
|
|
71
|
+
for k, v in stack_mapping.items():
|
|
72
|
+
data_color = self.color_scheme.stack_data if k not in diff_in_keys else self.color_scheme.diff
|
|
73
|
+
fmt = f'{style(hex(k), fg=self.color_scheme.address)}|+' \
|
|
74
|
+
f'{style(hex(offset), fg=self.color_scheme.stack_offset)}: ' \
|
|
75
|
+
f'{style(v, fg=data_color)}'
|
|
76
|
+
if offset == 0:
|
|
77
|
+
fmt += f'{"<-- $sp":^50}'
|
|
78
|
+
offset += WORD_SIZE
|
|
79
|
+
fmt_parts.append(fmt)
|
|
80
|
+
|
|
81
|
+
return super().__str__() + '\n'.join(fmt_parts)
|
|
82
|
+
|
|
83
|
+
def _create_mapping(self) -> Mapping[int, str]:
|
|
84
|
+
""" Generate mapping of stack address:data"""
|
|
85
|
+
base_addr = self.hilda.frame.sp
|
|
86
|
+
stack_mapping = {}
|
|
87
|
+
for i in range(0, self.depth * WORD_SIZE, WORD_SIZE):
|
|
88
|
+
current = base_addr + i
|
|
89
|
+
stack_mapping[current] = '0x' + self.hilda.symbol(current).peek(WORD_SIZE).hex()
|
|
90
|
+
return stack_mapping
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
class RegistersView(View):
|
|
94
|
+
""" Implements registers view """
|
|
95
|
+
DEFAULT_REGISTERS_TYPE = 'general'
|
|
96
|
+
|
|
97
|
+
def __init__(self, hilda_client, color_scheme, rtype=DEFAULT_REGISTERS_TYPE):
|
|
98
|
+
"""
|
|
99
|
+
:param hilda_client: hilda.hilda_client.HildaClient
|
|
100
|
+
:param rtype: str
|
|
101
|
+
:param color_scheme: hilda.ui.ui_manager.ColorScheme
|
|
102
|
+
|
|
103
|
+
`prev` saves the last registers stats inorder to perform diff check.
|
|
104
|
+
"""
|
|
105
|
+
super().__init__(hilda_client, 'Registers', color_scheme)
|
|
106
|
+
self.prev: Mapping[str, str] = None
|
|
107
|
+
self.rtype = rtype
|
|
108
|
+
|
|
109
|
+
def __str__(self) -> str:
|
|
110
|
+
""" Format registers view for printing"""
|
|
111
|
+
regs_mapping = self._create_mapping()
|
|
112
|
+
diff_in_keys = dict_diff(regs_mapping, self.prev)
|
|
113
|
+
self.prev = regs_mapping.copy()
|
|
114
|
+
list_of_lists = []
|
|
115
|
+
names = []
|
|
116
|
+
values = []
|
|
117
|
+
i = 0
|
|
118
|
+
|
|
119
|
+
# Divide the registers into columns of 16
|
|
120
|
+
for k, v in regs_mapping.items():
|
|
121
|
+
if i % 16 == 0 and i != 0:
|
|
122
|
+
list_of_lists.append(names.copy())
|
|
123
|
+
list_of_lists.append(values.copy())
|
|
124
|
+
names = []
|
|
125
|
+
values = []
|
|
126
|
+
|
|
127
|
+
names.append(style(k, fg=self.color_scheme.regs_name))
|
|
128
|
+
if k in diff_in_keys:
|
|
129
|
+
values.append(style(v, fg=self.color_scheme.diff))
|
|
130
|
+
else:
|
|
131
|
+
values.append(style(v, fg=self.color_scheme.regs_value))
|
|
132
|
+
i += 1
|
|
133
|
+
|
|
134
|
+
return super().__str__() + tabulate(list(zip(*list_of_lists)), tablefmt='plain', numalign='left')
|
|
135
|
+
|
|
136
|
+
def _create_mapping(self) -> Mapping[str, str]:
|
|
137
|
+
""" Generate mapping of registers name:data"""
|
|
138
|
+
regs = self._get_registers()
|
|
139
|
+
regs_mapping = {}
|
|
140
|
+
for reg in regs:
|
|
141
|
+
regs_mapping[reg.GetName()] = reg.GetValue()
|
|
142
|
+
return regs_mapping
|
|
143
|
+
|
|
144
|
+
def _get_registers(self):
|
|
145
|
+
"""
|
|
146
|
+
Returns list of registers grouped by type.
|
|
147
|
+
Available types: [general,floating]
|
|
148
|
+
:return: lldb.SBValueList
|
|
149
|
+
"""
|
|
150
|
+
registers_set = self.hilda.frame.GetRegisters()
|
|
151
|
+
for value in registers_set:
|
|
152
|
+
if self.rtype.lower() in value.GetName().lower():
|
|
153
|
+
return value
|
|
154
|
+
return None
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
class DisassemblyView(View):
|
|
158
|
+
""" Implements disassembly view """
|
|
159
|
+
DEFAULT_INSTRUCTION_COUNT = 5
|
|
160
|
+
DEFAULT_DISASSEMBLY_FLAVOR = 'intel'
|
|
161
|
+
|
|
162
|
+
def __init__(self, hilda_client, color_scheme, instruction_count=DEFAULT_INSTRUCTION_COUNT,
|
|
163
|
+
flavor=DEFAULT_DISASSEMBLY_FLAVOR):
|
|
164
|
+
"""
|
|
165
|
+
:param hilda_client: hilda.hilda_client.HildaClient
|
|
166
|
+
:param instruction_count: int
|
|
167
|
+
:param color_scheme: hilda.ui.ui_manager.ColorScheme
|
|
168
|
+
"""
|
|
169
|
+
super().__init__(hilda_client, 'Disassembly', color_scheme)
|
|
170
|
+
self.instruction_count = instruction_count
|
|
171
|
+
self.flavor = flavor
|
|
172
|
+
|
|
173
|
+
def __str__(self) -> str:
|
|
174
|
+
""" Format disassembly view for printing """
|
|
175
|
+
pc = self.hilda.frame.pc
|
|
176
|
+
target = self.hilda.target
|
|
177
|
+
|
|
178
|
+
disass = target.ReadInstructions(SBAddress(pc, target), self.instruction_count, self.flavor)
|
|
179
|
+
fmt_parts = []
|
|
180
|
+
for inst in disass:
|
|
181
|
+
load_addr = inst.addr.GetLoadAddress(self.hilda.target)
|
|
182
|
+
base_name = style(inst.addr.module.file.basename, self.color_scheme.basename)
|
|
183
|
+
addr = style(hex(load_addr), fg=self.color_scheme.address)
|
|
184
|
+
mnemonic = style(inst.GetMnemonic(self.hilda.target), fg=self.color_scheme.mnemonic)
|
|
185
|
+
operands = style(inst.GetOperands(self.hilda.target), fg=self.color_scheme.operands)
|
|
186
|
+
fmt = f'{base_name}[{addr}]: {mnemonic} {operands}'
|
|
187
|
+
if load_addr == self.hilda.frame.pc:
|
|
188
|
+
fmt += f'{"<-- $pc":^50}'
|
|
189
|
+
fmt_parts.append(fmt)
|
|
190
|
+
return super().__str__() + '\n'.join(fmt_parts)
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
class BackTraceView(View):
|
|
194
|
+
""" Implements backtrace view """
|
|
195
|
+
DEFAULT_BACKTRACE_DEPTH = 5
|
|
196
|
+
|
|
197
|
+
def __init__(self, hilda_client, color_scheme, depth=DEFAULT_BACKTRACE_DEPTH):
|
|
198
|
+
"""
|
|
199
|
+
:param hilda_client: hilda.hilda_client.HildaClient
|
|
200
|
+
:param depth: int
|
|
201
|
+
:param color_scheme: hilda.ui.ui_manager.ColorScheme
|
|
202
|
+
"""
|
|
203
|
+
super().__init__(hilda_client, 'BackTrace', color_scheme)
|
|
204
|
+
self.depth = depth
|
|
205
|
+
|
|
206
|
+
def __str__(self) -> str:
|
|
207
|
+
""" Format backtrace view for printing"""
|
|
208
|
+
bt = self.hilda.bt(should_print=False, depth=self.depth)
|
|
209
|
+
bt_colored = []
|
|
210
|
+
for pair in bt:
|
|
211
|
+
bt_colored.append(
|
|
212
|
+
[
|
|
213
|
+
style(pair[0], fg=self.color_scheme.address),
|
|
214
|
+
pair[1]
|
|
215
|
+
]
|
|
216
|
+
)
|
|
217
|
+
return super().__str__() + tabulate(bt_colored, tablefmt='plain', numalign='left')
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: hilda
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: LLDB wrapped and empowered by iPython's features
|
|
5
|
-
Author-email: doronz88 <doron88@gmail.com>, matan <matan1008@gmail.com>
|
|
5
|
+
Author-email: doronz88 <doron88@gmail.com>, matan <matan1008@gmail.com>, netanel <matan1008@gmail.com>
|
|
6
6
|
Maintainer-email: doronz88 <doron88@gmail.com>, matan <matan1008@gmail.com>
|
|
7
7
|
License: Copyright (c) 2012-2023 Doron Zarhi and Metan Perelman
|
|
8
8
|
|
|
@@ -47,6 +47,7 @@ Requires-Dist: click
|
|
|
47
47
|
Requires-Dist: objc-types-decoder
|
|
48
48
|
Requires-Dist: construct
|
|
49
49
|
Requires-Dist: pymobiledevice3
|
|
50
|
+
Requires-Dist: keystone-engine
|
|
50
51
|
Provides-Extra: test
|
|
51
52
|
Requires-Dist: pytest ; extra == 'test'
|
|
52
53
|
|
|
@@ -312,6 +313,65 @@ capabilities:
|
|
|
312
313
|
stop?
|
|
313
314
|
```
|
|
314
315
|
|
|
316
|
+
## UI Configuration
|
|
317
|
+
|
|
318
|
+
Hilda contains minimal UI for examining the target state.
|
|
319
|
+
The UI is divided into views:
|
|
320
|
+
|
|
321
|
+
- Registers
|
|
322
|
+
- Disassembly
|
|
323
|
+
- Stack
|
|
324
|
+
- Backtrace
|
|
325
|
+
|
|
326
|
+

|
|
327
|
+
|
|
328
|
+
This UI can be displayed at any time be executing:
|
|
329
|
+
|
|
330
|
+
```python
|
|
331
|
+
ui.show()
|
|
332
|
+
```
|
|
333
|
+
|
|
334
|
+
By default `step_into` and `step_over` will show this UI automatically.
|
|
335
|
+
You may disable this behaviour by executing:
|
|
336
|
+
|
|
337
|
+
```python
|
|
338
|
+
ui.active = False
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
Attentively, if you want to display UI after hitting a breakpoint, you can register `ui.show` as callback:
|
|
342
|
+
|
|
343
|
+
```python
|
|
344
|
+
symbol(0x7ff7b97c21b0).bp(ui.show)
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
Try playing with the UI settings by yourself:
|
|
348
|
+
|
|
349
|
+
```python
|
|
350
|
+
# Disable stack view
|
|
351
|
+
ui.views.stack.active = False
|
|
352
|
+
|
|
353
|
+
# View words from the stack
|
|
354
|
+
ui.views.stack.depth = 10
|
|
355
|
+
|
|
356
|
+
# View last 10 frames
|
|
357
|
+
ui.views.backtrace.depth = 10
|
|
358
|
+
|
|
359
|
+
# Disassemble 5 instructions
|
|
360
|
+
ui.views.disassembly.instruction_count = 5
|
|
361
|
+
|
|
362
|
+
# Change disassembly syntax to AT&T
|
|
363
|
+
ui.views.disassembly.flavor = 'att'
|
|
364
|
+
|
|
365
|
+
# View floating point registers
|
|
366
|
+
ui.views.registers.rtype = 'float'
|
|
367
|
+
|
|
368
|
+
# Change addresses print color
|
|
369
|
+
ui.colors.address = 'red'
|
|
370
|
+
|
|
371
|
+
# Change titles color
|
|
372
|
+
ui.color.title = 'green'
|
|
373
|
+
```
|
|
374
|
+
|
|
315
375
|
## Symbol objects
|
|
316
376
|
|
|
317
377
|
In Hilda, almost everything is wrapped using the `Symbol` Object. Symbol is just a nicer way for referring to addresses
|
|
@@ -6,9 +6,9 @@ hilda/from_ns_to_json.m,sha256=5Ddl0UJLQXlDYwR_yjE4yZk1aOsJGxoy1oRnhZHPrTw,2847
|
|
|
6
6
|
hilda/get_objectivec_class_description.m,sha256=Emqavl1i_qzVUYhg8b22mFhb0kZXQHPNB6vt_w-SUe0,4777
|
|
7
7
|
hilda/get_objectivec_symbol_data.m,sha256=xoxESO2iyMbTAkQPRste3ZWPYjqiC7QuixE3pHOML04,6421
|
|
8
8
|
hilda/hilda_ascii_art.html,sha256=-9YCjAKdGbjtdd6uoKrxkkcJq7j16r4dGka2bZ27b4o,120119
|
|
9
|
-
hilda/hilda_client.py,sha256=
|
|
9
|
+
hilda/hilda_client.py,sha256=lORoJ3K-few_ivri7PPDWN4IpinG0QE7bhHEvysEjUg,42180
|
|
10
10
|
hilda/launch_lldb.py,sha256=QaA5UFxaLWdLiEK839VbnyGLsY6sY0ODi1ge0-DlJsg,2855
|
|
11
|
-
hilda/lldb_entrypoint.py,sha256=
|
|
11
|
+
hilda/lldb_entrypoint.py,sha256=m5cUqnDCcqfgFTdlExMLjcq4F5L0gywuBIfFLnDLy8o,1006
|
|
12
12
|
hilda/lsof.m,sha256=FAtTc76-EFlWq1WTJkxYnNTnj0V8exPsiOH3rzAJAAA,3168
|
|
13
13
|
hilda/objective_c_class.py,sha256=CsvfWEIz8t5ew891DYIgCgf1UFcatiEYlTgpbtKSa44,11403
|
|
14
14
|
hilda/objective_c_symbol.py,sha256=OAH0eL0m__2XpwY-GKuPs-L8KSztWeqrUF8CfUDzGBQ,8611
|
|
@@ -24,7 +24,7 @@ hilda/snippets/fs_utils.py,sha256=97BKWXj6yuKxD6tDm3Nlaq6ACfET2oQFVwE2VlArw3E,39
|
|
|
24
24
|
hilda/snippets/remotepairingd.py,sha256=LxIMyXTl2YFoKMScs16s7vB5b8IFRdWead5tuKd5ZCw,5824
|
|
25
25
|
hilda/snippets/syslog.py,sha256=8qhYHKTElzWifqYAwt72iQ57wf1n0F_au2Vl2L8NPOc,294
|
|
26
26
|
hilda/snippets/uuid.py,sha256=ttw-rq2Wshm7UMZXd5uYP37bi8G_ZE4XcXJbsYIgp1c,273
|
|
27
|
-
hilda/snippets/xpc.py,sha256=
|
|
27
|
+
hilda/snippets/xpc.py,sha256=GM6AN7UuJ0niE51PXdrh0WzYT-u2V1mPDOUwDTiiAEo,3909
|
|
28
28
|
hilda/snippets/mach/CFRunLoopServiceMachPort_hooks.py,sha256=nAFZ4TjjBy0BlffbsKnTneGa0YE_T9bPNv5qhPVR-Hw,4156
|
|
29
29
|
hilda/snippets/mach/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
30
30
|
hilda/snippets/macho/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -33,9 +33,12 @@ hilda/snippets/macho/apple_version.py,sha256=TTaqZKMviXJoU1o3OYeUskmxSkhVhh3UG1V
|
|
|
33
33
|
hilda/snippets/macho/image_info.py,sha256=862C3T2-pPCwgdRqJTNNv28gECwGigJiZojUIFGIKqg,1588
|
|
34
34
|
hilda/snippets/macho/macho.py,sha256=X4NQZkO7VCcIMNuPs25ukiBrHM5Kj3UPMJzzeILfuyg,839
|
|
35
35
|
hilda/snippets/macho/macho_load_commands.py,sha256=KF-HCr46iQloOwnLfFPUYi0dn9ehywSoy1R_P-BqMPI,10644
|
|
36
|
-
hilda
|
|
37
|
-
hilda
|
|
38
|
-
hilda
|
|
39
|
-
hilda-0.
|
|
40
|
-
hilda-0.
|
|
41
|
-
hilda-0.
|
|
36
|
+
hilda/ui/colors.json,sha256=f-ITquY3IInQreviTy23JfmxfJrGM1_MivACf1GKGqM,262
|
|
37
|
+
hilda/ui/ui_manager.py,sha256=BmzI1sBx0PYCQDlB9Al7wsTEAMJxaJ7NW0DS4C7g5-0,2265
|
|
38
|
+
hilda/ui/views.py,sha256=Sd0y7I0iQ4HAWJNyDQ6LjvbEtJYolCaC2sAuPWs6-EE,7693
|
|
39
|
+
hilda-0.3.0.dist-info/LICENSE,sha256=M-LVJ0AFAYB82eueyl8brh-QLPe-iLNVgbCi79-3TDo,1078
|
|
40
|
+
hilda-0.3.0.dist-info/METADATA,sha256=ALa5ZPU4GoOsKqZgMATXZMtQj4oSxEfQUonznBxl3xE,22234
|
|
41
|
+
hilda-0.3.0.dist-info/WHEEL,sha256=AtBG6SXL3KF_v0NxLf0ehyVOh0cold-JbJYXNGorC6Q,92
|
|
42
|
+
hilda-0.3.0.dist-info/entry_points.txt,sha256=9n3O3j6V3XnVR_GcFqCWNgRAbalfukTSW2WvghsLVmA,46
|
|
43
|
+
hilda-0.3.0.dist-info/top_level.txt,sha256=nyNxC_JClCNn-Oi_JFapvV2VrlMk4x47b2mnwP5OJik,6
|
|
44
|
+
hilda-0.3.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|