hilda 2.0.16__py3-none-any.whl → 3.0.1__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/_version.py +9 -4
- hilda/breakpoints.py +480 -0
- hilda/hilda_client.py +80 -305
- hilda/ipython_extensions/keybindings.py +34 -11
- hilda/launch_lldb.py +29 -12
- hilda/objective_c_class.py +2 -6
- hilda/snippets/mach/CFRunLoopServiceMachPort_hooks.py +2 -5
- hilda/snippets/macho/all_image_infos.py +7 -4
- hilda/symbol.py +3 -0
- hilda/watchpoints.py +237 -0
- {hilda-2.0.16.dist-info → hilda-3.0.1.dist-info}/METADATA +15 -15
- {hilda-2.0.16.dist-info → hilda-3.0.1.dist-info}/RECORD +16 -14
- {hilda-2.0.16.dist-info → hilda-3.0.1.dist-info}/WHEEL +1 -1
- {hilda-2.0.16.dist-info → hilda-3.0.1.dist-info}/LICENSE +0 -0
- {hilda-2.0.16.dist-info → hilda-3.0.1.dist-info}/entry_points.txt +0 -0
- {hilda-2.0.16.dist-info → hilda-3.0.1.dist-info}/top_level.txt +0 -0
hilda/launch_lldb.py
CHANGED
|
@@ -61,6 +61,33 @@ class LLDBListenerThread(Thread, ABC):
|
|
|
61
61
|
sys.stderr.write(stderr)
|
|
62
62
|
stderr = self.process.GetSTDERR(1024)
|
|
63
63
|
|
|
64
|
+
def _process_potential_watchpoint_event(self) -> None:
|
|
65
|
+
stopped_threads = self._get_stopped_threads(lldb.eStopReasonWatchpoint)
|
|
66
|
+
for thread in stopped_threads:
|
|
67
|
+
watchpoint_id = thread.GetStopReasonDataAtIndex(0)
|
|
68
|
+
frame = thread.GetFrameAtIndex(0)
|
|
69
|
+
if lldb.hilda_client is not None:
|
|
70
|
+
lldb.hilda_client.watchpoints._dispatch_watchpoint_callback(watchpoint_id, thread, frame)
|
|
71
|
+
|
|
72
|
+
def _get_stopped_threads(self, reason: Optional[int] = None) -> list[lldb.SBThread]:
|
|
73
|
+
if reason is None:
|
|
74
|
+
stop_reasons = [
|
|
75
|
+
lldb.eStopReasonSignal, lldb.eStopReasonException,
|
|
76
|
+
lldb.eStopReasonBreakpoint, lldb.eStopReasonWatchpoint,
|
|
77
|
+
lldb.eStopReasonPlanComplete, lldb.eStopReasonTrace,
|
|
78
|
+
]
|
|
79
|
+
else:
|
|
80
|
+
stop_reasons = [reason]
|
|
81
|
+
|
|
82
|
+
return [thread for thread in self.process if thread.GetStopReason() in stop_reasons]
|
|
83
|
+
|
|
84
|
+
def _set_selected_thread_to_stopped_thread(self) -> None:
|
|
85
|
+
stopped_threads = self._get_stopped_threads()
|
|
86
|
+
if len(stopped_threads) < 1:
|
|
87
|
+
return
|
|
88
|
+
thread = stopped_threads[0]
|
|
89
|
+
self.process.SetSelectedThread(thread)
|
|
90
|
+
|
|
64
91
|
def run(self):
|
|
65
92
|
event = lldb.SBEvent()
|
|
66
93
|
last_state = lldb.eStateStopped
|
|
@@ -87,18 +114,8 @@ class LLDBListenerThread(Thread, ABC):
|
|
|
87
114
|
logger.debug('Process Continued')
|
|
88
115
|
elif state == lldb.eStateStopped and last_state == lldb.eStateRunning:
|
|
89
116
|
logger.debug('Process Stopped')
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
stop_reason = thread.GetStopReason()
|
|
93
|
-
logger.debug(f'tid = {hex(thread.GetThreadID())} pc = {frame.GetPC()}')
|
|
94
|
-
if stop_reason not in [lldb.eStopReasonSignal, lldb.eStopReasonException,
|
|
95
|
-
lldb.eStopReasonBreakpoint,
|
|
96
|
-
lldb.eStopReasonWatchpoint, lldb.eStopReasonPlanComplete,
|
|
97
|
-
lldb.eStopReasonTrace,
|
|
98
|
-
lldb.eStopReasonSignal]:
|
|
99
|
-
continue
|
|
100
|
-
self.process.SetSelectedThread(thread)
|
|
101
|
-
break
|
|
117
|
+
self._set_selected_thread_to_stopped_thread()
|
|
118
|
+
self._process_potential_watchpoint_event()
|
|
102
119
|
|
|
103
120
|
last_state = state
|
|
104
121
|
|
hilda/objective_c_class.py
CHANGED
|
@@ -4,7 +4,6 @@ from collections import namedtuple
|
|
|
4
4
|
from dataclasses import dataclass, field
|
|
5
5
|
from functools import partial
|
|
6
6
|
from typing import Any
|
|
7
|
-
from uuid import uuid4
|
|
8
7
|
|
|
9
8
|
from objc_types_decoder.decode import decode as decode_type
|
|
10
9
|
from objc_types_decoder.decode import decode_with_tail
|
|
@@ -188,19 +187,16 @@ class Class:
|
|
|
188
187
|
hilda.log_info('removing breakpoints')
|
|
189
188
|
for bp_id, bp in list(hilda.breakpoints.items()):
|
|
190
189
|
if 'group_uuid' in bp.options and bp.options.get('group_uuid', '') == options['group_uuid']:
|
|
191
|
-
hilda.
|
|
190
|
+
hilda.breakpoints.remove(bp_id)
|
|
192
191
|
captured = hilda.evaluate_expression('$arg1')
|
|
193
192
|
captured = captured.objc_symbol
|
|
194
193
|
hilda.captured_objects[options['name'].split(' ')[0].split('[')[1]] = captured
|
|
195
194
|
hilda.cont()
|
|
196
195
|
|
|
197
|
-
group_uuid = str(uuid4())
|
|
198
|
-
|
|
199
196
|
for method in self.methods:
|
|
200
197
|
if not method.is_class:
|
|
201
198
|
# only instance methods are relevant for capturing self
|
|
202
|
-
method.imp.bp(hook
|
|
203
|
-
name=f'-[{class_name} {method.name}]')
|
|
199
|
+
method.imp.bp(hook)
|
|
204
200
|
|
|
205
201
|
if sync:
|
|
206
202
|
self._client.cont()
|
|
@@ -22,11 +22,8 @@ def _disable_internal_error_handling() -> None:
|
|
|
22
22
|
hilda.CFRunLoopServiceMachPort_while_ea = int(hilda.file_symbol(eval(while_ea)))
|
|
23
23
|
elif instruction.GetMnemonic(hilda.target) in ('brk', 'ud2'):
|
|
24
24
|
symbol = hilda.symbol(instruction.addr.GetLoadAddress(hilda.target))
|
|
25
|
-
symbol.
|
|
26
|
-
|
|
27
|
-
forced=True,
|
|
28
|
-
name=f'__CFRunLoopServiceMachPort-brk-{int(symbol - hilda.symbols.__CFRunLoopServiceMachPort)}'
|
|
29
|
-
)
|
|
25
|
+
description = f'__CFRunLoopServiceMachPort-brk-{int(symbol - hilda.symbols.__CFRunLoopServiceMachPort)}'
|
|
26
|
+
symbol.bp(_CFRunLoopServiceMachPort_hook, guarded=True, description=description)
|
|
30
27
|
|
|
31
28
|
if hilda.arch == 'x86_64h':
|
|
32
29
|
return
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
|
|
3
|
+
import inquirer3
|
|
3
4
|
from construct import Array, CString, Hex, If, Int32ub, Int32ul, Int64ul, Pointer, Struct, Tell, this
|
|
4
|
-
from
|
|
5
|
+
from inquirer3 import List
|
|
5
6
|
|
|
6
7
|
from hilda.lldb_importer import lldb
|
|
7
8
|
from hilda.snippets.macho.image_info import ImageInfo, dyld_image_info_t
|
|
@@ -104,9 +105,11 @@ class AllImageInfos:
|
|
|
104
105
|
|
|
105
106
|
@staticmethod
|
|
106
107
|
def __select_specific_image(images):
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
108
|
+
image_list = [image.file_path for image in images]
|
|
109
|
+
logging.info('Multiple images were found with that prefix.\n'
|
|
110
|
+
'Please select one:\n'
|
|
111
|
+
f'{image_list}')
|
|
112
|
+
selected_image_path = inquirer3.prompt(List('selected_image_path', image_list))['selected_image_path']
|
|
110
113
|
for image in images:
|
|
111
114
|
if image.file_path == selected_image_path:
|
|
112
115
|
return image
|
hilda/symbol.py
CHANGED
|
@@ -145,6 +145,9 @@ class Symbol(int):
|
|
|
145
145
|
def monitor(self, **args):
|
|
146
146
|
return self._client.monitor(self, **args)
|
|
147
147
|
|
|
148
|
+
def watch(self, **args):
|
|
149
|
+
return self._client.watchpoints.add(self, **args)
|
|
150
|
+
|
|
148
151
|
def bp(self, callback=None, **args):
|
|
149
152
|
return self._client.bp(self, callback, **args)
|
|
150
153
|
|
hilda/watchpoints.py
ADDED
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
from typing import Callable, Generator, Optional, Union
|
|
2
|
+
|
|
3
|
+
from hilda.lldb_importer import lldb
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class HildaWatchpoint:
|
|
7
|
+
"""
|
|
8
|
+
Hilda's class representing an LLDB watchpoint, with some optional additional properties
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
def __init__(self, hilda, lldb_watchpoint: lldb.SBWatchpoint, where: Optional[int] = None) -> None:
|
|
12
|
+
"""
|
|
13
|
+
Initialize a watchpoint list.
|
|
14
|
+
|
|
15
|
+
:param hilda.hilda_client.HildaClient hilda: Hilda client
|
|
16
|
+
"""
|
|
17
|
+
self._hilda = hilda
|
|
18
|
+
self._where = where
|
|
19
|
+
self._callback = None
|
|
20
|
+
|
|
21
|
+
# Actual watchpoint from LLDB API
|
|
22
|
+
self.lldb_watchpoint = lldb_watchpoint
|
|
23
|
+
|
|
24
|
+
@property
|
|
25
|
+
def where(self) -> Optional[int]:
|
|
26
|
+
"""
|
|
27
|
+
A value identifying where the watchpoint was set (when it was created).
|
|
28
|
+
|
|
29
|
+
It could be either an address (int) or a Hilda symbol object (Symbol, that inherits from int).
|
|
30
|
+
"""
|
|
31
|
+
return self._where
|
|
32
|
+
|
|
33
|
+
@property
|
|
34
|
+
def id(self) -> int:
|
|
35
|
+
""" A number identifying the watchpoint. """
|
|
36
|
+
return self.lldb_watchpoint.GetID()
|
|
37
|
+
|
|
38
|
+
@property
|
|
39
|
+
def callback(self) -> Optional[Callable]:
|
|
40
|
+
"""
|
|
41
|
+
A callback that will be executed when the watchpoint is hit.
|
|
42
|
+
|
|
43
|
+
Note that unless the callback explicitly continues (by calling `cont()`), the program will not continue.
|
|
44
|
+
The callback will be invoked as callback(hilda, *args), where hilda is the 'HildaClient'.
|
|
45
|
+
"""
|
|
46
|
+
return self._callback
|
|
47
|
+
|
|
48
|
+
@callback.setter
|
|
49
|
+
def callback(self, callback: Optional[Callable]) -> None:
|
|
50
|
+
self._callback = callback
|
|
51
|
+
|
|
52
|
+
@property
|
|
53
|
+
def condition(self) -> Optional[str]:
|
|
54
|
+
"""
|
|
55
|
+
An LLDB expression to make this a conditional watchpoint.
|
|
56
|
+
"""
|
|
57
|
+
return self.lldb_watchpoint.GetCondition()
|
|
58
|
+
|
|
59
|
+
@condition.setter
|
|
60
|
+
def condition(self, condition: Optional[str]) -> None:
|
|
61
|
+
self.lldb_watchpoint.SetCondition(condition)
|
|
62
|
+
|
|
63
|
+
def __repr__(self) -> str:
|
|
64
|
+
return f'<{self.__class__.__name__} LLDB:{self.lldb_watchpoint} CALLBACK:{self.callback}>'
|
|
65
|
+
|
|
66
|
+
def __str__(self) -> str:
|
|
67
|
+
return repr(self)
|
|
68
|
+
|
|
69
|
+
def remove(self) -> None:
|
|
70
|
+
"""
|
|
71
|
+
Remove the watchpoint.
|
|
72
|
+
"""
|
|
73
|
+
self._hilda.watchpoints.remove(self)
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
class WatchpointList:
|
|
77
|
+
"""
|
|
78
|
+
Manager for `HildaWatchpoint` objects, each one wrapping another native LLDB watchpoint.
|
|
79
|
+
"""
|
|
80
|
+
|
|
81
|
+
def __init__(self, hilda) -> None:
|
|
82
|
+
"""
|
|
83
|
+
Initialize a watchpoint list.
|
|
84
|
+
|
|
85
|
+
:param hilda.hilda_client.HildaClient hilda: Hilda client
|
|
86
|
+
"""
|
|
87
|
+
self._hilda = hilda
|
|
88
|
+
self._watchpoints = {}
|
|
89
|
+
|
|
90
|
+
def __contains__(self, id_or_wp: Union[int, HildaWatchpoint]) -> bool:
|
|
91
|
+
return self.get(id_or_wp) is not None
|
|
92
|
+
|
|
93
|
+
def __iter__(self) -> Generator[HildaWatchpoint, None, None]:
|
|
94
|
+
for wp in self._hilda.target.watchpoint_iter():
|
|
95
|
+
yield self[wp.GetID()]
|
|
96
|
+
|
|
97
|
+
def __len__(self) -> int:
|
|
98
|
+
return self._hilda.target.GetNumWatchpoints()
|
|
99
|
+
|
|
100
|
+
def __getitem__(self, id_or_wp: Union[int, HildaWatchpoint]) -> HildaWatchpoint:
|
|
101
|
+
"""
|
|
102
|
+
Get a watchpoint by ID (or the watchpoint itself, though it usually makes little sense)
|
|
103
|
+
|
|
104
|
+
:param id_or_wp: Watchpoint's ID (or the watchpoint itself)
|
|
105
|
+
"""
|
|
106
|
+
wp = self.get(id_or_wp)
|
|
107
|
+
if wp is None:
|
|
108
|
+
raise KeyError(id_or_wp)
|
|
109
|
+
|
|
110
|
+
return wp
|
|
111
|
+
|
|
112
|
+
def __delitem__(self, id_or_wp: Union[int, HildaWatchpoint]):
|
|
113
|
+
"""
|
|
114
|
+
Remove a watchpoint.
|
|
115
|
+
|
|
116
|
+
:param id_or_wp: Watchpoint's ID (or the watchpoint itself)
|
|
117
|
+
"""
|
|
118
|
+
self.remove(id_or_wp)
|
|
119
|
+
|
|
120
|
+
def __repr__(self) -> str:
|
|
121
|
+
return repr(dict(self.items()))
|
|
122
|
+
|
|
123
|
+
def __str__(self) -> str:
|
|
124
|
+
return repr(self)
|
|
125
|
+
|
|
126
|
+
def get(self, id_or_wp: Union[int, HildaWatchpoint]) -> Optional[HildaWatchpoint]:
|
|
127
|
+
"""
|
|
128
|
+
Get a watchpoint by ID or the watchpoint itself.
|
|
129
|
+
|
|
130
|
+
:param id_or_wp: Watchpoint's ID (or the watchpoint itself)
|
|
131
|
+
:return: `HildaWatchpoint` is one exists, or `None` otherwise
|
|
132
|
+
"""
|
|
133
|
+
|
|
134
|
+
if isinstance(id_or_wp, int):
|
|
135
|
+
wp = self._hilda.target.FindWatchpointByID(id_or_wp)
|
|
136
|
+
elif isinstance(id_or_wp, HildaWatchpoint):
|
|
137
|
+
wp = id_or_wp.lldb_watchpoint
|
|
138
|
+
else:
|
|
139
|
+
raise KeyError(f'Watchpoint "{id_or_wp}" could not be found')
|
|
140
|
+
|
|
141
|
+
if not wp.IsValid():
|
|
142
|
+
return None
|
|
143
|
+
|
|
144
|
+
wp_id = wp.GetID()
|
|
145
|
+
if wp_id not in self._watchpoints:
|
|
146
|
+
self._hilda.log_debug(f'Found a watchpoint added outside of the Hilda API {wp}')
|
|
147
|
+
self._watchpoints[wp_id] = HildaWatchpoint(self._hilda, wp)
|
|
148
|
+
|
|
149
|
+
return self._watchpoints[wp_id]
|
|
150
|
+
|
|
151
|
+
def add(self, where: int, size: int = 8, read: bool = True, write: bool = True,
|
|
152
|
+
callback: Optional[Callable] = None, condition: str = None) -> HildaWatchpoint:
|
|
153
|
+
"""
|
|
154
|
+
Add a watchpoint.
|
|
155
|
+
|
|
156
|
+
:param where: The address of the watchpoint.
|
|
157
|
+
:param size: The size of the watchpoint (the address span to watch).
|
|
158
|
+
:param read: The watchpoint should monitor reads from memory in the specified address (and size).
|
|
159
|
+
:param write: The watchpoint should monitor writes to memory in the specified address (and size).
|
|
160
|
+
:param callback: A callback that will be executed when the watchpoint is hit.
|
|
161
|
+
Note that unless the callback explicitly continues (by calling cont()), the program will not continue.
|
|
162
|
+
The callback will be invoked as callback(hilda, *args), where hilda is the 'HildaClient'.
|
|
163
|
+
:param condition: An LLDB expression to make this a conditional watchpoint.
|
|
164
|
+
:return: The new watchpoint
|
|
165
|
+
"""
|
|
166
|
+
|
|
167
|
+
error = lldb.SBError()
|
|
168
|
+
wp = self._hilda.target.WatchAddress(where, size, read, write, error)
|
|
169
|
+
if not wp.IsValid():
|
|
170
|
+
raise Exception(f'Failed to create watchpoint at {where} ({error})')
|
|
171
|
+
|
|
172
|
+
wp = HildaWatchpoint(self._hilda, wp, where)
|
|
173
|
+
wp.callback = callback
|
|
174
|
+
wp.condition = condition
|
|
175
|
+
|
|
176
|
+
self._watchpoints[wp.id] = wp
|
|
177
|
+
|
|
178
|
+
self._hilda.log_info(f'Watchpoint #{wp.id} has been set')
|
|
179
|
+
return wp
|
|
180
|
+
|
|
181
|
+
def remove(self, id_or_wp: Union[int, HildaWatchpoint]) -> None:
|
|
182
|
+
"""
|
|
183
|
+
Remove a watchpoint.
|
|
184
|
+
|
|
185
|
+
:param id_or_wp: Watchpoint's ID (or the watchpoint itself)
|
|
186
|
+
"""
|
|
187
|
+
wp = self[id_or_wp]
|
|
188
|
+
watchpoint_id = wp.id
|
|
189
|
+
self._hilda.target.DeleteWatchpoint(watchpoint_id)
|
|
190
|
+
self._hilda.log_debug(f'Watchpoint #{watchpoint_id} has been removed')
|
|
191
|
+
|
|
192
|
+
def clear(self) -> None:
|
|
193
|
+
"""
|
|
194
|
+
Remove all watchpoints
|
|
195
|
+
"""
|
|
196
|
+
for wp in list(self):
|
|
197
|
+
self.remove(wp)
|
|
198
|
+
|
|
199
|
+
def show(self) -> None:
|
|
200
|
+
""" Show existing watchpoints. """
|
|
201
|
+
for wp in self:
|
|
202
|
+
message = f'🚨 Watchpoint #{wp.id}'
|
|
203
|
+
|
|
204
|
+
if wp.where is not None:
|
|
205
|
+
message += f'\n\tWhere: {wp.where}'
|
|
206
|
+
|
|
207
|
+
self._hilda.log_info(message)
|
|
208
|
+
|
|
209
|
+
def items(self) -> Generator[tuple[int, HildaWatchpoint], None, None]:
|
|
210
|
+
"""
|
|
211
|
+
Get a watchpoint ID and watchpoint object tuple for every watchpoint.
|
|
212
|
+
"""
|
|
213
|
+
return ((wp.id, wp) for wp in self)
|
|
214
|
+
|
|
215
|
+
def keys(self) -> Generator[int, None, None]:
|
|
216
|
+
"""
|
|
217
|
+
Get the watchpoint ID for every watchpoint.
|
|
218
|
+
"""
|
|
219
|
+
return (wp.id for wp in self)
|
|
220
|
+
|
|
221
|
+
def values(self) -> Generator[HildaWatchpoint, None, None]:
|
|
222
|
+
"""
|
|
223
|
+
Get the watchpoint object for every watchpoint.
|
|
224
|
+
"""
|
|
225
|
+
return (wp for wp in self)
|
|
226
|
+
|
|
227
|
+
def _dispatch_watchpoint_callback(self, watchpoint_id: int, _, frame) -> None:
|
|
228
|
+
"""
|
|
229
|
+
Route the watchpoint callback the specific watchpoint callback.
|
|
230
|
+
"""
|
|
231
|
+
self._hilda._bp_frame = frame
|
|
232
|
+
try:
|
|
233
|
+
callback = self[watchpoint_id].callback
|
|
234
|
+
if callback is not None:
|
|
235
|
+
callback(self._hilda, frame, None, self[watchpoint_id])
|
|
236
|
+
finally:
|
|
237
|
+
self._hilda._bp_frame = None
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.2
|
|
2
2
|
Name: hilda
|
|
3
|
-
Version:
|
|
3
|
+
Version: 3.0.1
|
|
4
4
|
Summary: LLDB wrapped and empowered by iPython's features
|
|
5
5
|
Author-email: doronz88 <doron88@gmail.com>, matan <matan1008@gmail.com>, netanel cohen <netanelc305@protonmail.com>
|
|
6
6
|
Maintainer-email: doronz88 <doron88@gmail.com>, matan <matan1008@gmail.com>, netanel cohen <netanelc305@protonmail.com>
|
|
@@ -52,6 +52,7 @@ Requires-Dist: pymobiledevice3
|
|
|
52
52
|
Requires-Dist: keystone-engine
|
|
53
53
|
Requires-Dist: tabulate
|
|
54
54
|
Requires-Dist: inquirer3
|
|
55
|
+
Requires-Dist: traitlets
|
|
55
56
|
Provides-Extra: test
|
|
56
57
|
Requires-Dist: pytest; extra == "test"
|
|
57
58
|
|
|
@@ -162,7 +163,7 @@ Have a nice flight ✈️! Starting an IPython shell...
|
|
|
162
163
|
Here is a gist of methods you can access from `p`:
|
|
163
164
|
|
|
164
165
|
- `hd`
|
|
165
|
-
- Print
|
|
166
|
+
- Print a hexdump of given buffer
|
|
166
167
|
- `lsof`
|
|
167
168
|
- Get dictionary of all open FDs
|
|
168
169
|
- `bt`
|
|
@@ -209,7 +210,7 @@ Here is a gist of methods you can access from `p`:
|
|
|
209
210
|
- Simulate a call to an objc selector
|
|
210
211
|
- `call`
|
|
211
212
|
- Call function at given address with given parameters
|
|
212
|
-
- `monitor`
|
|
213
|
+
- `monitor` or `breakpoints.add_monitor`
|
|
213
214
|
- Monitor every time a given address is called
|
|
214
215
|
|
|
215
216
|
The following options are available:
|
|
@@ -254,10 +255,10 @@ Here is a gist of methods you can access from `p`:
|
|
|
254
255
|
- Step into current instruction.
|
|
255
256
|
- `step_over`
|
|
256
257
|
- Step over current instruction.
|
|
257
|
-
- `
|
|
258
|
-
- Remove all breakpoints
|
|
259
|
-
- `
|
|
260
|
-
- Remove a single breakpoint
|
|
258
|
+
- `breakpoints.clear`
|
|
259
|
+
- Remove all breakpoints
|
|
260
|
+
- `breakpoints.remove`
|
|
261
|
+
- Remove a single breakpoint
|
|
261
262
|
- `force_return`
|
|
262
263
|
- Prematurely return from a stack frame, short-circuiting exection of newer frames and optionally
|
|
263
264
|
yielding a specified value.
|
|
@@ -265,14 +266,10 @@ Here is a gist of methods you can access from `p`:
|
|
|
265
266
|
- Print information about currently running mapped process.
|
|
266
267
|
- `print_proc_entitlements`
|
|
267
268
|
- Get the plist embedded inside the process' __LINKEDIT section.
|
|
268
|
-
- `bp`
|
|
269
|
+
- `bp` or `breakpoints.add`
|
|
269
270
|
- Add a breakpoint
|
|
270
|
-
- `
|
|
271
|
-
- Show existing breakpoints
|
|
272
|
-
- `save`
|
|
273
|
-
- Save loaded symbols map (for loading later using the load() command)
|
|
274
|
-
- `load`
|
|
275
|
-
- Load an existing symbols map (previously saved by the save() command)
|
|
271
|
+
- `breakpoints.show`
|
|
272
|
+
- Show existing breakpoints
|
|
276
273
|
- `po`
|
|
277
274
|
- Print given object using LLDB's po command
|
|
278
275
|
Can also run big chunks of native code:
|
|
@@ -326,6 +323,9 @@ Sometimes accessing the [Python API](#python-api) can be tiring, so we added som
|
|
|
326
323
|
|
|
327
324
|
#### Key-bindings
|
|
328
325
|
|
|
326
|
+
- **F1**: Show banner help message
|
|
327
|
+
- **F2**: Show process state UI
|
|
328
|
+
- **F3**: Toggle stdout/stderr enablement
|
|
329
329
|
- **F7**: Step Into
|
|
330
330
|
- **F8**: Step Over
|
|
331
331
|
- **F9**: Continue
|
|
@@ -531,7 +531,7 @@ s.bp(scripted_breakpoint)
|
|
|
531
531
|
p.bp('symbol_name')
|
|
532
532
|
|
|
533
533
|
# In case you need to specify a specific library it's loaded from
|
|
534
|
-
p.bp('symbol_name',
|
|
534
|
+
p.bp(('symbol_name', 'ModuleName'))
|
|
535
535
|
```
|
|
536
536
|
|
|
537
537
|
#### Globalized symbols
|
|
@@ -3,22 +3,24 @@ gifs/ui.png,sha256=iaRwNZ9qVWUkUe2TJb_6VPsTu--7HrElA2duWiyZ-Oc,131
|
|
|
3
3
|
gifs/xpc_print_message.gif,sha256=i5S8Y9bJm9n-NtOipFTAC8_jUR4uZCM4sOap_ccJX0k,939935
|
|
4
4
|
hilda/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
5
5
|
hilda/__main__.py,sha256=KWRqvukK4wraxCMtvH5nO25mFXLO5aWXa7z_VfAtbO8,90
|
|
6
|
-
hilda/_version.py,sha256=
|
|
6
|
+
hilda/_version.py,sha256=LoHm4tYT8EC9S2qaIOxZkFh7b3UUZ5jNAQr7bVyLo6Q,511
|
|
7
|
+
hilda/breakpoints.py,sha256=ZVszQf4WtRgjM2JAn8E-b-Ve6kzVg5VwvTHv5_wGjwQ,19198
|
|
7
8
|
hilda/cli.py,sha256=PCjrI7GrERIrZCODJYmPt6eyl-nPYZviTS8fBG3oIjM,3618
|
|
8
9
|
hilda/common.py,sha256=El-ih7cvCv9PJ5OWb1jkCbh4GuaRD6gqlrFC5gyY-TE,498
|
|
9
10
|
hilda/exceptions.py,sha256=8L1OvOqns4O4ieiH4YlrMbZkk_PvuyCq4UyqFAodkF8,2042
|
|
10
11
|
hilda/hilda_ascii_art.html,sha256=-9YCjAKdGbjtdd6uoKrxkkcJq7j16r4dGka2bZ27b4o,120119
|
|
11
|
-
hilda/hilda_client.py,sha256=
|
|
12
|
-
hilda/launch_lldb.py,sha256
|
|
12
|
+
hilda/hilda_client.py,sha256=phSwiI3XfuLzMXlUw7-irbZbEgi7sEpDz2w7EGUUhf0,38897
|
|
13
|
+
hilda/launch_lldb.py,sha256=-lmxif-w53oeTCea6ZHLiYHChkMpdDDO_zgTFWpAU6E,8597
|
|
13
14
|
hilda/lldb_entrypoint.py,sha256=vTiClzfiTtjorlxEfIsI-W657KEGobx74qDhaZ8nPhM,1007
|
|
14
15
|
hilda/lldb_importer.py,sha256=TCGpAWwiBuyNRsbgcYawiqm35t8XQLCJwoOfEqyBeik,526
|
|
15
|
-
hilda/objective_c_class.py,sha256=
|
|
16
|
+
hilda/objective_c_class.py,sha256=AFGXFDkYUoHf_LVS6GJSyvMsIIYIviLx0PCa-f4pCT8,11561
|
|
16
17
|
hilda/objective_c_symbol.py,sha256=lIZHef5iZe3AeUsK0uIsDtFnzSM-Ad6i2wfdj9DwLUM,8269
|
|
17
18
|
hilda/registers.py,sha256=-9kk1MuKnWlJ0Z8zZ2RPV9nGRDtX1GXhCSkEvfnCktA,848
|
|
18
|
-
hilda/symbol.py,sha256=
|
|
19
|
+
hilda/symbol.py,sha256=UIDmnNq1tx1uORqgRNaO_gfW2y17mhyy4cz83UVFhcc,7623
|
|
19
20
|
hilda/symbols_jar.py,sha256=Vqdv6iH92P6aSfcz5XiR0FbNRqKuUu48mi-GxvPr32w,6504
|
|
21
|
+
hilda/watchpoints.py,sha256=j5wLEORXUkxeamjI2F61QXRrSXcGsbs4XTmN1UEa_A4,7895
|
|
20
22
|
hilda/ipython_extensions/events.py,sha256=w_4V8FoJJMarWArEE8uzb2UXk1mqfslmI7XCyVb_XuE,1976
|
|
21
|
-
hilda/ipython_extensions/keybindings.py,sha256=
|
|
23
|
+
hilda/ipython_extensions/keybindings.py,sha256=W_Cnh8lG5yVdK5x0A-4UeyBsoJBufbYl54Mqrbo8OwM,1922
|
|
22
24
|
hilda/ipython_extensions/magics.py,sha256=ULb63-OyIaWwvSfwRvEG_65ibaI2RTxeX8yPJK8pbc0,1300
|
|
23
25
|
hilda/objective_c/from_ns_to_json.m,sha256=5Ddl0UJLQXlDYwR_yjE4yZk1aOsJGxoy1oRnhZHPrTw,2847
|
|
24
26
|
hilda/objective_c/get_objectivec_class_by_module.m,sha256=DC8S8XaWsQSOJZWVWhATr98SZQobA3MmclLsBJGZTcU,704
|
|
@@ -36,10 +38,10 @@ hilda/snippets/remotepairingd.py,sha256=w7SYctpKw3B56ZP26n4Ap5_hz6VmZiUbe8CrTmZ1
|
|
|
36
38
|
hilda/snippets/syslog.py,sha256=8qhYHKTElzWifqYAwt72iQ57wf1n0F_au2Vl2L8NPOc,294
|
|
37
39
|
hilda/snippets/uuid.py,sha256=ttw-rq2Wshm7UMZXd5uYP37bi8G_ZE4XcXJbsYIgp1c,273
|
|
38
40
|
hilda/snippets/xpc.py,sha256=Z0e4b1lIScZg7fsSwGK43v363qp25fdzYcc7ajJsyhU,3960
|
|
39
|
-
hilda/snippets/mach/CFRunLoopServiceMachPort_hooks.py,sha256=
|
|
41
|
+
hilda/snippets/mach/CFRunLoopServiceMachPort_hooks.py,sha256=8e6184bcRhqSDqXyDu-jnIXDbdw-mnP15J4MgNBKyg4,4202
|
|
40
42
|
hilda/snippets/mach/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
41
43
|
hilda/snippets/macho/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
42
|
-
hilda/snippets/macho/all_image_infos.py,sha256=
|
|
44
|
+
hilda/snippets/macho/all_image_infos.py,sha256=dwuf4vhewP1EvtcCa65IIVqWyDeFYxoBcqygpWK2INw,4866
|
|
43
45
|
hilda/snippets/macho/apple_version.py,sha256=TTaqZKMviXJoU1o3OYeUskmxSkhVhh3UG1VbdJ6N-LE,148
|
|
44
46
|
hilda/snippets/macho/image_info.py,sha256=Onu6u61TwFOwAfENpZIQA9N-Ba3b_M0gr8r6THNdIR4,1605
|
|
45
47
|
hilda/snippets/macho/macho.py,sha256=X4NQZkO7VCcIMNuPs25ukiBrHM5Kj3UPMJzzeILfuyg,839
|
|
@@ -47,9 +49,9 @@ hilda/snippets/macho/macho_load_commands.py,sha256=vUWfFM2H6o8dMglXV7rHgh-EMTzS0
|
|
|
47
49
|
hilda/ui/colors.json,sha256=f-ITquY3IInQreviTy23JfmxfJrGM1_MivACf1GKGqM,262
|
|
48
50
|
hilda/ui/ui_manager.py,sha256=BmzI1sBx0PYCQDlB9Al7wsTEAMJxaJ7NW0DS4C7g5-0,2265
|
|
49
51
|
hilda/ui/views.py,sha256=bzClOgKirKYs6nhsNRXpkGNIg3oIOmFb659GLWrlTdo,7792
|
|
50
|
-
hilda-
|
|
51
|
-
hilda-
|
|
52
|
-
hilda-
|
|
53
|
-
hilda-
|
|
54
|
-
hilda-
|
|
55
|
-
hilda-
|
|
52
|
+
hilda-3.0.1.dist-info/LICENSE,sha256=M-LVJ0AFAYB82eueyl8brh-QLPe-iLNVgbCi79-3TDo,1078
|
|
53
|
+
hilda-3.0.1.dist-info/METADATA,sha256=S0GZw7zb-oTZXZGaW_zD_eBq0ba3EaA6Zs3OSZAI3qI,23354
|
|
54
|
+
hilda-3.0.1.dist-info/WHEEL,sha256=52BFRY2Up02UkjOa29eZOS2VxUrpPORXg1pkohGGUS8,91
|
|
55
|
+
hilda-3.0.1.dist-info/entry_points.txt,sha256=9n3O3j6V3XnVR_GcFqCWNgRAbalfukTSW2WvghsLVmA,46
|
|
56
|
+
hilda-3.0.1.dist-info/top_level.txt,sha256=TVD7l1WkE1noT866YqPFhiQnjYCYZM5Xz54v_3EYpnI,11
|
|
57
|
+
hilda-3.0.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|