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 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
- print(row)
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
- lldb.hilda_client.interactive()
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.2.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
+ ![img.png](gifs/ui.png)
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=XF6Ndyc7NxxQ1y-IlBJdPASD-NwD2Gx8DK2FeFrNsu4,41527
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=Cjj520dApKCiBUNeCbOACFrZV8zU2QUBgHFAmxwWH5w,900
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=Idb6-IZkEIHsfNcv13IN_WgMH1FG5OekX2yriiAvTO0,3629
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-0.2.0.dist-info/LICENSE,sha256=M-LVJ0AFAYB82eueyl8brh-QLPe-iLNVgbCi79-3TDo,1078
37
- hilda-0.2.0.dist-info/METADATA,sha256=BoaHbTOFhMgTqygcngpLjmgJ5RpaW3zmJXJzw3zgx9I,21063
38
- hilda-0.2.0.dist-info/WHEEL,sha256=pkctZYzUS4AYVn6dJ-7367OJZivF2e8RA9b_ZBjif18,92
39
- hilda-0.2.0.dist-info/entry_points.txt,sha256=9n3O3j6V3XnVR_GcFqCWNgRAbalfukTSW2WvghsLVmA,46
40
- hilda-0.2.0.dist-info/top_level.txt,sha256=nyNxC_JClCNn-Oi_JFapvV2VrlMk4x47b2mnwP5OJik,6
41
- hilda-0.2.0.dist-info/RECORD,,
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,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.40.0)
2
+ Generator: bdist_wheel (0.41.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
File without changes