Skip to content

Commit e81bd17

Browse files
committed
trying to sqeeze some speed
1 parent e815968 commit e81bd17

File tree

4 files changed

+35
-8
lines changed

4 files changed

+35
-8
lines changed

DEVELOPMENT.md

+7
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,13 @@ We currently develop with backwards compatible python3 in mind.
99
Functions may be annotated inline `dev like(this: str) -> None:`.
1010
However to annotate types, we prefer to add type comments (PEP something) `like = this # type: str`.
1111

12+
## Profiling
13+
14+
For speed, ucf kills the python vm with the internal `os._exit` instead of doing a clean `exit`.
15+
This, however, trips profiling tools.
16+
17+
In case you want to run a profiler (or other biz), run ucf with `UCF_DEBUG_CLEAN_SHUTDOWN=1`.
18+
1219
## Debugging
1320

1421
There are different layers to be debugged.

ucf

+4-2
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,8 @@ import os
99
from typing import Any, Callable, Iterable
1010

1111
from unicorefuzz import configspec
12-
from unicorefuzz.angr_harness import AngrHarness
1312
from unicorefuzz.configspec import serialize_spec, UNICOREFUZZ_SPEC
1413
from unicorefuzz.harness import Harness
15-
from unicorefuzz.probe_wrapper import ProbeWrapper
1614
from unicorefuzz.unicorefuzz import Unicorefuzz
1715

1816

@@ -51,6 +49,8 @@ def wrap_probe(args: argparse.Namespace) -> None:
5149
Attach, break and forward memory from target
5250
Former probewrapper.py
5351
"""
52+
from unicorefuzz.probe_wrapper import ProbeWrapper
53+
5454
ProbeWrapper(load_conf(args)).wrap_gdb_target()
5555

5656

@@ -69,6 +69,8 @@ def run_angr(args: argparse.Namespace) -> None:
6969
Drop the memory in the angr harness and start concolic execution
7070
Former angr-harness.py
7171
"""
72+
from unicorefuzz.angr_harness import AngrHarness
73+
7274
AngrHarness(load_conf(args)).get_angry(args.input_file)
7375

7476

unicorefuzz/harness.py

+21-5
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,14 @@
33
Main (Unicorn-)Harness, used alongside AFL.
44
"""
55
import argparse
6+
import gc
67
import os
78
import sys
89
import time
910
from typing import Optional, Tuple, Dict, List
1011

1112
from capstone import Cs
1213
from unicorn import *
13-
from unicorn.x86_const import *
1414

1515
from unicorefuzz import x64utils
1616
from unicorefuzz.unicorefuzz import (
@@ -102,13 +102,21 @@ def harness(self, input_file: str, wait: bool, debug: bool, trace: bool) -> None
102102
:param debug: if we should enable unicorn debugger
103103
:param trace: trace or not
104104
"""
105+
106+
# Exit without clean python vm shutdown:
107+
# "The os._exit() function can be used if it is absolutely positively necessary to exit immediately"
108+
# Many times faster!
109+
# noinspection PyProtectedMember
110+
exit_func = os._exit if not os.getenv("UCF_DEBUG_CLEAN_SHUTDOWN") else exit
111+
105112
uc, entry, exits = self.uc_init(
106113
input_file, wait, trace, verbose=(debug or trace)
107114
)
108115
if debug:
109116
self.uc_debug(uc, entry_point=entry, exit_point=exits[0])
110117
else:
111118
self.uc_run(uc, entry, exits[0])
119+
exit_func(0)
112120

113121
def uc_init(
114122
self, input_file, wait: bool = False, trace: bool = False, verbose: bool = False
@@ -161,13 +169,25 @@ def uc_init(
161169
# On error: map memory, add exits.
162170
uc.hook_add(UC_HOOK_MEM_UNMAPPED, unicorn_debug_mem_invalid_access, self)
163171

172+
# import gc
173+
# gc.collect()
174+
if os.getenv("UCF_DEBUG_MEMORY"):
175+
from pympler import muppy, summary
176+
177+
all_objects = muppy.get_objects()
178+
sum1 = summary.summarize(all_objects)
179+
summary.print_(sum1)
180+
164181
# Last chance to hook before forkserver starts (if running as afl child)
165182
debug_sleep = os.getenv("UCF_DEBUG_SLEEP_BEFORE_FORK")
166183
if debug_sleep:
167184
print(
168185
"[d] Sleeping. Forkserver will start in {} seconds.".format(debug_sleep)
169186
)
170187
time.sleep(float(debug_sleep))
188+
189+
gc.collect()
190+
171191
# starts the afl forkserver. Won't fork if afl is not around.
172192
self.uc_start_forkserver(uc, exits)
173193

@@ -237,10 +257,6 @@ def uc_run(self, uc: Uc, entry_point: int, exit_point: int) -> None:
237257
)
238258
)
239259
self.force_crash(e)
240-
# Exit without clean python vm shutdown:
241-
# "The os._exit() function can be used if it is absolutely positively necessary to exit immediately"
242-
# Many times faster!
243-
os._exit(0)
244260

245261
def map_known_mem(self, uc: Uc):
246262
"""

unicorefuzz/unicorefuzz.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -78,16 +78,18 @@
7878
"armbe": ARMBE,
7979
}
8080

81+
8182
# emulate from @begin, and stop when reaching address @until
8283
def uc_forkserver_init(uc: Uc, exits: List[int]) -> None:
8384
import ctypes
84-
from unicorn import unicorn, UC_ERR_OK, UcError
85+
from unicorn import unicorn
8586

8687
exit_count = len(exits)
8788
unicorn._uc.uc_afl_forkserver_init(
8889
uc._uch, ctypes.c_size_t(exit_count), (ctypes.c_uint64 * exit_count)(*exits)
8990
)
9091

92+
9193
def regs_from_unicorn(arch: Architecture) -> List[str]:
9294
"""
9395
Get all (supported) registers of an arch from Unicorn constants

0 commit comments

Comments
 (0)