Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Redex crashes with specific input during regalloc pass with compiler optimisations disabled #256

Closed
deephole opened this issue Sep 1, 2017 · 15 comments

Comments

@deephole
Copy link

deephole commented Sep 1, 2017

I've used https://github.com/google/iosched application as an input file with with following configuration:
{
"redex" : {
"passes" : [
"RegAllocPass",
"InstructionSelectionPass"
]
}
}
Default redex binary with all the compiler optimisations turned on works perfectly fine but if you compile with -O0 the process crashes during regalloc pass:
`deephole-MBP:redex-master deep.hole$ ./redex.py app-debug.apk -c config/default.config (modified)
Using config config/default.config
Using binary (default)
Extracting apk...
Detected dex mode Api21DexMode
Unpacking dex files
Detecting Application Modules
Unpacking APK finished in 0.31 seconds
Running redex-all on 2 dex files
Running redex binary at /Users/deep.hole/Downloads/redex-master/redex-all
Verify-none mode: No
Loading classes from dex from /var/folders/cc/gz_1p6j11hvglj_h79vhpg300000gn/T/tmpajr924pl.redex_dexen/dex0/classes.dex
Loading classes from dex from /var/folders/cc/gz_1p6j11hvglj_h79vhpg300000gn/T/tmpajr924pl.redex_dexen/dex1/classes2.dex
Load classes from dexes completed in 1.4 seconds
Deobfuscating dex elements completed in 0.3 seconds
Initializing reachable classes completed in 0.3 seconds
Processing proguard rules completed in 0.1 seconds
Evaluating RegAllocPass...
RegAllocPass (eval) completed in 0.0 seconds
Evaluating InstructionSelectionPass...
InstructionSelectionPass (eval) completed in 0.0 seconds
Running RegAllocPass...
Traceback (most recent call last):
File "./redex.py", line 152, in run_pass
subprocess.check_call(args, env=env)
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/subprocess.py", line 291, in check_call
raise CalledProcessError(retcode, cmd)
subprocess.CalledProcessError: Command '['/Users/deep.hole/Downloads/redex-master/redex-all', '--apkdir', '/var/folders/cc/gz_1p6j11hvglj_h79vhpg300000gn/T/tmpvh5d59zw.redex_extracted_apk', '--outdir', '/var/folders/cc/gz_1p6j11hvglj_h79vhpg300000gn/T/tmpajr924pl.redex_dexen', '--config', 'config/default.config', '/var/folders/cc/gz_1p6j11hvglj_h79vhpg300000gn/T/tmpajr924pl.redex_dexen/dex0/classes.dex', '/var/folders/cc/gz_1p6j11hvglj_h79vhpg300000gn/T/tmpajr924pl.redex_dexen/dex1/classes2.dex']' died with <Signals.SIGILL: 4>.

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "./redex.py", line 636, in
run_redex(args)
File "./redex.py", line 568, in run_redex
debugger)
File "./redex.py", line 165, in run_pass
'by running %(lldb_script_name)s') % script_filenames)
RuntimeError: redex-all crashed with exit code -4! You can re-run it under gdb by running /var/folders/cc/gz_1p6j11hvglj_h79vhpg300000gn/T/redex-gdb-ao9k29_m.sh or under lldb by running /var/folders/cc/gz_1p6j11hvglj_h79vhpg300000gn/T/redex-lldb-ccxr_1zu.sh
deephole-MBP:redex-master deep.hole$ `

I didn't manage to extract crash logs from vanilla redex, but on my forked project where I'm using ASAN and cmake crashlog looks like this :

`Evaluating InstructionSelectionPass...
InstructionSelectionPass (eval) completed in 0.0 seconds
Running RegAllocPass...
ASAN:DEADLYSIGNAL

==49993==ERROR: AddressSanitizer: stack-overflow on address 0x700000645f40 (pc 0x000109726186 bp 0x700000646310 sp 0x700000645f40 T18)
#0 0x109726185 in std::__1::__hash_iterator<std::__1::__hash_node<Block*, void*>> std::__1::__hash_table<Block, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >::find<Block*>(Block* const&) __hash_table:2169
#1 0x10a33c475 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) unordered_set:558
#2 0x10a33f864 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) Transform.cpp:99
#3 0x10a33f864 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) Transform.cpp:99
#4 0x10a33f864 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) Transform.cpp:99
#5 0x10a33f864 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) Transform.cpp:99
#6 0x10a33f864 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) Transform.cpp:99
#7 0x10a33f864 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) Transform.cpp:99
#8 0x10a33f864 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) Transform.cpp:99
#9 0x10a33f864 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) Transform.cpp:99
#10 0x10a33f864 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) Transform.cpp:99
#11 0x10a33f864 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) Transform.cpp:99
#12 0x10a33f864 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) Transform.cpp:99
#13 0x10a33f864 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) Transform.cpp:99
#14 0x10a33f864 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) Transform.cpp:99
#15 0x10a33f864 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) Transform.cpp:99
#16 0x10a33f864 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) Transform.cpp:99
#17 0x10a33f864 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) Transform.cpp:99
#18 0x10a33f864 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) Transform.cpp:99
#19 0x10a33f864 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) Transform.cpp:99
#20 0x10a33f864 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) Transform.cpp:99
#21 0x10a33f864 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) Transform.cpp:99
#22 0x10a33f864 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) Transform.cpp:99
#23 0x10a33f864 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) Transform.cpp:99
#24 0x10a33f864 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) Transform.cpp:99
#25 0x10a33f864 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) Transform.cpp:99
#26 0x10a33f864 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) Transform.cpp:99
#27 0x10a33f864 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) Transform.cpp:99
#28 0x10a33f864 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) Transform.cpp:99
#29 0x10a33f864 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) Transform.cpp:99
#30 0x10a33f864 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) Transform.cpp:99
#31 0x10a33f864 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) Transform.cpp:99
#32 0x10a33f864 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) Transform.cpp:99
#33 0x10a33f864 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) Transform.cpp:99
#34 0x10a33f864 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) Transform.cpp:99
#35 0x10a33f864 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) Transform.cpp:99
#36 0x10a33f864 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) Transform.cpp:99
#37 0x10a33f864 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) Transform.cpp:99
#38 0x10a33f864 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) Transform.cpp:99
#39 0x10a33f864 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) Transform.cpp:99
#40 0x10a33f864 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) Transform.cpp:99
#41 0x10a33f864 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) Transform.cpp:99
#42 0x10a33f864 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) Transform.cpp:99
#43 0x10a33f864 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) Transform.cpp:99
#44 0x10a33f864 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) Transform.cpp:99
#45 0x10a33f864 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) Transform.cpp:99
#46 0x10a33f864 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) Transform.cpp:99
#47 0x10a33f864 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) Transform.cpp:99
#48 0x10a33f864 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) Transform.cpp:99
#49 0x10a33f864 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) Transform.cpp:99
#50 0x10a33f864 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) Transform.cpp:99
#51 0x10a33f864 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) Transform.cpp:99
#52 0x10a33f864 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) Transform.cpp:99
#53 0x10a33f864 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) Transform.cpp:99
#54 0x10a33f864 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) Transform.cpp:99
#55 0x10a33f864 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) Transform.cpp:99
#56 0x10a33f864 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) Transform.cpp:99
#57 0x10a33f864 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) Transform.cpp:99
#58 0x10a33f864 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) Transform.cpp:99
#59 0x10a33f864 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) Transform.cpp:99
#60 0x10a33f864 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) Transform.cpp:99
#61 0x10a33f864 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) Transform.cpp:99
#62 0x10a33f864 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) Transform.cpp:99
#63 0x10a33f864 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) Transform.cpp:99
#64 0x10a33f864 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) Transform.cpp:99
#65 0x10a33f864 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) Transform.cpp:99
#66 0x10a33f864 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) Transform.cpp:99
#67 0x10a33f864 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) Transform.cpp:99
#68 0x10a33f864 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) Transform.cpp:99
#69 0x10a33f864 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) Transform.cpp:99
#70 0x10a33f864 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) Transform.cpp:99
#71 0x10a33f864 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) Transform.cpp:99
#72 0x10a33f864 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) Transform.cpp:99
#73 0x10a33f864 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) Transform.cpp:99
#74 0x10a33f864 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) Transform.cpp:99
#75 0x10a33f864 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) Transform.cpp:99
#76 0x10a33f864 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) Transform.cpp:99
#77 0x10a33f864 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) Transform.cpp:99
#78 0x10a33f864 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) Transform.cpp:99
#79 0x10a33f864 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) Transform.cpp:99
#80 0x10a33f864 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) Transform.cpp:99
#81 0x10a33f864 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) Transform.cpp:99
#82 0x10a33f864 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) Transform.cpp:99
#83 0x10a33f864 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) Transform.cpp:99
#84 0x10a33f864 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) Transform.cpp:99
#85 0x10a33f864 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) Transform.cpp:99
#86 0x10a33f864 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) Transform.cpp:99
#87 0x10a33f864 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) Transform.cpp:99
#88 0x10a33f864 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) Transform.cpp:99
#89 0x10a33f864 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) Transform.cpp:99
#90 0x10a33f864 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) Transform.cpp:99
#91 0x10a33f864 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) Transform.cpp:99
#92 0x10a33f864 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) Transform.cpp:99
#93 0x10a33f864 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) Transform.cpp:99
#94 0x10a33f864 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) Transform.cpp:99
#95 0x10a33f864 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) Transform.cpp:99
#96 0x10a33f864 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) Transform.cpp:99
#97 0x10a33f864 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) Transform.cpp:99
#98 0x10a33f864 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) Transform.cpp:99
#99 0x10a33f864 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) Transform.cpp:99
#100 0x10a33f864 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) Transform.cpp:99
#101 0x10a33f864 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) Transform.cpp:99
#102 0x10a33f864 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) Transform.cpp:99
#103 0x10a33f864 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) Transform.cpp:99
#104 0x10a33f864 in transform::visit(Block*, std::__1::unordered_set<Block*, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >&) Transform.cpp:99
#105 0x1099c39a0 in ControlFlowGraph::ControlFlowGraph(IRCode*, bool) ControlFlow.cpp:191
#106 0x1099cff4b in ControlFlowGraph::ControlFlowGraph(IRCode*, bool) ControlFlow.cpp:63
#107 0x109e5389b in IRCode::build_cfg(bool) memory:3153
#108 0x1098cd43a in RegAllocPass::run_pass(std::__1::vector<DexStore, std::__1::allocator >&, ConfigFiles&, PassManager&)::$_0::operator()(std::nullptr_t&, DexMethod*) const RegAlloc.cpp:86
#109 0x1098cbe81 in regalloc::graph_coloring::Allocator::Stats walk_methods_parallel<std::nullptr_t, regalloc::graph_coloring::Allocator::Stats, std::__1::vector<DexClass*, std::__1::allocator<DexClass*> >, RegAllocPass::run_pass(std::__1::vector<DexStore, std::__1::allocator >&, ConfigFiles&, PassManager&)::$_0, RegAllocPass::run_pass(std::__1::vector<DexStore, std::__1::allocator >&, ConfigFiles&, PassManager&)::$_1, RegAllocPass::run_pass(std::__1::vector<DexStore, std::__1::allocator >&, ConfigFiles&, PassManager&)::$_2>(std::__1::vector<DexClass*, std::__1::allocator<DexClass*> > const&, RegAllocPass::run_pass(std::__1::vector<DexStore, std::__1::allocator >&, ConfigFiles&, PassManager&)::$_0, RegAllocPass::run_pass(std::__1::vector<DexStore, std::__1::allocator >&, ConfigFiles&, PassManager&)::$_1, RegAllocPass::run_pass(std::__1::vector<DexStore, std::__1::allocator >&, ConfigFiles&, PassManager&)::$_2, regalloc::graph_coloring::Allocator::Stats const&, unsigned long)::'lambda'(std::nullptr_t&, DexClass*)::operator()(std::nullptr_t&, DexClass*) const ParallelWalkers.h:50
#110 0x1098cb399 in regalloc::graph_coloring::Allocator::Stats std::__1::__invoke_void_return_wrapperregalloc::graph_coloring::Allocator::Stats::__call<regalloc::graph_coloring::Allocator::Stats walk_methods_parallel<std::nullptr_t, regalloc::graph_coloring::Allocator::Stats, std::__1::vector<DexClass*, std::__1::allocator<DexClass*> >, RegAllocPass::run_pass(std::__1::vector<DexStore, std::__1::allocator >&, ConfigFiles&, PassManager&)::$_0, RegAllocPass::run_pass(std::__1::vector<DexStore, std::__1::allocator >&, ConfigFiles&, PassManager&)::$_1, RegAllocPass::run_pass(std::__1::vector<DexStore, std::__1::allocator >&, ConfigFiles&, PassManager&)::$_2>(std::__1::vector<DexClass*, std::__1::allocator<DexClass*> > const&, RegAllocPass::run_pass(std::__1::vector<DexStore, std::__1::allocator >&, ConfigFiles&, PassManager&)::$_0, RegAllocPass::run_pass(std::__1::vector<DexStore, std::__1::allocator >&, ConfigFiles&, PassManager&)::$_1, RegAllocPass::run_pass(std::__1::vector<DexStore, std::__1::allocator >&, ConfigFiles&, PassManager&)::$_2, regalloc::graph_coloring::Allocator::Stats const&, unsigned long)::'lambda'(std::nullptr_t&, DexClass*)&, std::nullptr_t&, DexClass*>(regalloc::graph_coloring::Allocator::Stats walk_methods_parallel<std::nullptr_t, regalloc::graph_coloring::Allocator::Stats, std::__1::vector<DexClass*, std::__1::allocator<DexClass*> >, RegAllocPass::run_pass(std::__1::vector<DexStore, std::__1::allocator >&, ConfigFiles&, PassManager&)::$_0, RegAllocPass::run_pass(std::__1::vector<DexStore, std::__1::allocator >&, ConfigFiles&, PassManager&)::$_1, RegAllocPass::run_pass(std::__1::vector<DexStore, std::__1::allocator >&, ConfigFiles&, PassManager&)::$_2>(std::__1::vector<DexClass*, std::__1::allocator<DexClass*> > const&, RegAllocPass::run_pass(std::__1::vector<DexStore, std::__1::allocator >&, ConfigFiles&, PassManager&)::$_0, RegAllocPass::run_pass(std::__1::vector<DexStore, std::__1::allocator >&, ConfigFiles&, PassManager&)::$_1, RegAllocPass::run_pass(std::__1::vector<DexStore, std::__1::allocator >&, ConfigFiles&, PassManager&)::$_2, regalloc::graph_coloring::Allocator::Stats const&, unsigned long)::'lambda'(std::nullptr_t&, DexClass*)&&&, std::nullptr_t&&&, DexClass*&&) __functional_base:416
#111 0x1098cb14f in std::__1::__function::__func<regalloc::graph_coloring::Allocator::Stats walk_methods_parallel<std::nullptr_t, regalloc::graph_coloring::Allocator::Stats, std::__1::vector<DexClass*, std::__1::allocator<DexClass*> >, RegAllocPass::run_pass(std::__1::vector<DexStore, std::__1::allocator >&, ConfigFiles&, PassManager&)::$_0, RegAllocPass::run_pass(std::__1::vector<DexStore, std::__1::allocator >&, ConfigFiles&, PassManager&)::$_1, RegAllocPass::run_pass(std::__1::vector<DexStore, std::__1::allocator >&, ConfigFiles&, PassManager&)::$_2>(std::__1::vector<DexClass*, std::__1::allocator<DexClass*> > const&, RegAllocPass::run_pass(std::__1::vector<DexStore, std::__1::allocator >&, ConfigFiles&, PassManager&)::$_0, RegAllocPass::run_pass(std::__1::vector<DexStore, std::__1::allocator >&, ConfigFiles&, PassManager&)::$_1, RegAllocPass::run_pass(std::__1::vector<DexStore, std::__1::allocator >&, ConfigFiles&, PassManager&)::$_2, regalloc::graph_coloring::Allocator::Stats const&, unsigned long)::'lambda'(std::nullptr_t&, DexClass*), std::__1::allocator<regalloc::graph_coloring::Allocator::Stats walk_methods_parallel<std::nullptr_t, regalloc::graph_coloring::Allocator::Stats, std::__1::vector<DexClass*, std::__1::allocator<DexClass*> >, RegAllocPass::run_pass(std::__1::vector<DexStore, std::__1::allocator >&, ConfigFiles&, PassManager&)::$_0, RegAllocPass::run_pass(std::__1::vector<DexStore, std::__1::allocator >&, ConfigFiles&, PassManager&)::$_1, RegAllocPass::run_pass(std::__1::vector<DexStore, std::__1::allocator >&, ConfigFiles&, PassManager&)::$_2>(std::__1::vector<DexClass*, std::__1::allocator<DexClass*> > const&, RegAllocPass::run_pass(std::__1::vector<DexStore, std::__1::allocator >&, ConfigFiles&, PassManager&)::$_0, RegAllocPass::run_pass(std::__1::vector<DexStore, std::__1::allocator >&, ConfigFiles&, PassManager&)::$_1, RegAllocPass::run_pass(std::__1::vector<DexStore, std::__1::allocator >&, ConfigFiles&, PassManager&)::$_2, regalloc::graph_coloring::Allocator::Stats const&, unsigned long)::'lambda'(std::nullptr_t&, DexClass*)>, regalloc::graph_coloring::Allocator::Stats (std::nullptr_t&, DexClass*)>::operator()(std::nullptr_t&, DexClass*&&) functional:1437
#112 0x1098f0a7c in std::__1::function<regalloc::graph_coloring::Allocator::Stats (std::nullptr_t&, DexClass*)>::operator()(std::nullptr_t&, DexClass*) const functional:1817
#113 0x1098eee39 in WorkQueue<DexClass*, std::nullptr_t, regalloc::graph_coloring::Allocator::Stats>::consume(WorkerState<DexClass*, std::nullptr_t, regalloc::graph_coloring::Allocator::Stats>, DexClass) WorkQueue.h:76
#114 0x1098ec118 in WorkQueue<DexClass*, std::nullptr_t, regalloc::graph_coloring::Allocator::Stats>::run_all(regalloc::graph_coloring::Allocator::Stats const&)::'lambda'(WorkerState<DexClass*, std::nullptr_t, regalloc::graph_coloring::Allocator::Stats>, unsigned long)::operator()(WorkerState<DexClass, std::nullptr_t, regalloc::graph_coloring::Allocator::Stats>, unsigned long) const WorkQueue.h:185
#115 0x1098eb248 in void
std::__1::__thread_proxy<std::__1::tuple<WorkQueue<DexClass*, std::nullptr_t, regalloc::graph_coloring::Allocator::Stats>::run_all(regalloc::graph_coloring::Allocator::Stats const&)::'lambda'(WorkerState<DexClass*, std::nullptr_t, regalloc::graph_coloring::Allocator::Stats>, unsigned long), WorkerState<DexClass, std::nullptr_t, regalloc::graph_coloring::Allocator::Stats>, unsigned long> >(void) __functional_base:416
#116 0x7fffa774a93a in _pthread_body (libsystem_pthread.dylib:x86_64+0x393a)
#117 0x7fffa774a886 in _pthread_start (libsystem_pthread.dylib:x86_64+0x3886)
#118 0x7fffa774a08c in thread_start (libsystem_pthread.dylib:x86_64+0x308c)

SUMMARY: AddressSanitizer: stack-overflow __hash_table:2169 in std::__1::__hash_iterator<std::__1::__hash_node<Block*, void*>> std::__1::__hash_table<Block, std::__1::hash<Block*>, std::__1::equal_to<Block*>, std::__1::allocator<Block*> >::find<Block*>(Block* const&)
Thread T18 created by T0 here:
#0 0x10bf2fca6 in wrap_pthread_create (libclang_rt.asan_osx_dynamic.dylib:x86_64h+0x4cca6)
#1 0x1098ea70f in std::__1::thread::thread<WorkQueue<DexClass*, std::nullptr_t, regalloc::graph_coloring::Allocator::Stats>::run_all(regalloc::graph_coloring::Allocator::Stats const&)::'lambda'(WorkerState<DexClass*, std::nullptr_t, regalloc::graph_coloring::Allocator::Stats>, unsigned long)&, WorkerState<DexClass, std::nullptr_t, regalloc::graph_coloring::Allocator::Stats>, unsigned long&, void>(WorkQueue<DexClass, std::nullptr_t, regalloc::graph_coloring::Allocator::Stats>::run_all(regalloc::graph_coloring::Allocator::Stats const&)::'lambda'(WorkerState<DexClass*, std::nullptr_t, regalloc::graph_coloring::Allocator::Stats>, unsigned long)&&&, WorkerState<DexClass, std::nullptr_t, regalloc::graph_coloring::Allocator::Stats>&&, unsigned long&&&) thread:369
#2 0x1098e9c5c in std::__1::thread::thread<WorkQueue<DexClass
, std::nullptr_t, regalloc::graph_coloring::Allocator::Stats>::run_all(regalloc::graph_coloring::Allocator::Stats const&)::'lambda'(WorkerState<DexClass*, std::nullptr_t, regalloc::graph_coloring::Allocator::Stats>, unsigned long)&, WorkerState<DexClass, std::nullptr_t, regalloc::graph_coloring::Allocator::Stats>, unsigned long&, void>(WorkQueue<DexClass, std::nullptr_t, regalloc::graph_coloring::Allocator::Stats>::run_all(regalloc::graph_coloring::Allocator::Stats const&)::'lambda'(WorkerState<DexClass*, std::nullptr_t, regalloc::graph_coloring::Allocator::Stats>, unsigned long)&&&, WorkerState<DexClass, std::nullptr_t, regalloc::graph_coloring::Allocator::Stats>&&, unsigned long&&&) thread:365
#3 0x1098e9a5f in void std::__1::vector<std::__1::thread, std::__1::allocatorstd::__1::thread >::__emplace_back_slow_path<WorkQueue<DexClass
, std::nullptr_t, regalloc::graph_coloring::Allocator::Stats>::run_all(regalloc::graph_coloring::Allocator::Stats const&)::'lambda'(WorkerState<DexClass*, std::nullptr_t, regalloc::graph_coloring::Allocator::Stats>, unsigned long)&, WorkerState<DexClass, std::nullptr_t, regalloc::graph_coloring::Allocator::Stats>, unsigned long&>(WorkQueue<DexClass, std::nullptr_t, regalloc::graph_coloring::Allocator::Stats>::run_all(regalloc::graph_coloring::Allocator::Stats const&)::'lambda'(WorkerState<DexClass*, std::nullptr_t, regalloc::graph_coloring::Allocator::Stats>, unsigned long)&&&, WorkerState<DexClass, std::nullptr_t, regalloc::graph_coloring::Allocator::Stats>&&, unsigned long&&&) memory:1752
#4 0x1098c729f in WorkQueue<DexClass
, std::nullptr_t, regalloc::graph_coloring::Allocator::Stats>::run_all(regalloc::graph_coloring::Allocator::Stats const&) vector:1650
#5 0x1098c53be in regalloc::graph_coloring::Allocator::Stats walk_methods_parallel<std::nullptr_t, regalloc::graph_coloring::Allocator::Stats, std::__1::vector<DexClass*, std::__1::allocator<DexClass*> >, RegAllocPass::run_pass(std::__1::vector<DexStore, std::__1::allocator >&, ConfigFiles&, PassManager&)::$_0, RegAllocPass::run_pass(std::__1::vector<DexStore, std::__1::allocator >&, ConfigFiles&, PassManager&)::$_1, RegAllocPass::run_pass(std::__1::vector<DexStore, std::__1::allocator >&, ConfigFiles&, PassManager&)::$_2>(std::__1::vector<DexClass*, std::__1::allocator<DexClass*> > const&, RegAllocPass::run_pass(std::__1::vector<DexStore, std::__1::allocator >&, ConfigFiles&, PassManager&)::$_0, RegAllocPass::run_pass(std::__1::vector<DexStore, std::__1::allocator >&, ConfigFiles&, PassManager&)::$_1, RegAllocPass::run_pass(std::__1::vector<DexStore, std::__1::allocator >&, ConfigFiles&, PassManager&)::$_2, regalloc::graph_coloring::Allocator::Stats const&, unsigned long) ParallelWalkers.h:65
#6 0x1098c3aa3 in RegAllocPass::run_pass(std::__1::vector<DexStore, std::__1::allocator >&, ConfigFiles&, PassManager&) RegAlloc.cpp:62
#7 0x109f9a6c6 in PassManager::run_passes(std::__1::vector<DexStore, std::__1::allocator >&, std::__1::vector<DexClass*, std::__1::allocator<DexClass*> > const&, ConfigFiles&) PassManager.cpp:141
#8 0x1091fe660 in (anonymous namespace)::runOptimizationPasses(ConfigFiles&, std::__1::vector<DexStore, std::__1::allocator >&, redex::ProguardConfiguration const&, Json::Value const&, std::__1::vector<
#19 0x7fffa7531234 in start (libdyld.dylib:x86_64+0x5234)

==49993==ABORTING

Process finished with exit code 6`

@deephole deephole changed the title Redex crashes with specific input on regalloc pass and compiler optimisations disabled Redex crashes with specific input during regalloc pass with compiler optimisations disabled Sep 1, 2017
@justinjhendrick
Copy link
Contributor

justinjhendrick commented Sep 1, 2017

huh. Interesting. Thanks for the detailed error log.

I looked at transform::visit and it looks correct. Maybe this method is just too big for recursive searching (uh-oh).

Could temporarily you put this line:

TRACE(CFG, 1, "building CFG for method with %d blocks\n", m_blocks.size());

before the call to visit, please? Then, run it again and paste the output.

@deephole
Copy link
Author

deephole commented Sep 4, 2017

Here are the requested logs:
https://drive.google.com/open?id=0BzoBQPp1Gv3MaG1HZHpYeC1nM2s
Please note that this issue only appears with compiler optimisations off CXXFLAGS='-g -O0

@justinjhendrick
Copy link
Contributor

The method this crashes on has 329 blocks. I wouldn't think that would be too large. Could you show me the output of ulimit -s on this machine, please?

@justinjhendrick
Copy link
Contributor

I've rewritten visit with a loop instead of recursion. That change should land tomorrow.

@deephole
Copy link
Author

deephole commented Sep 7, 2017

Recent commit fixed initial issue. Unfortunately now I'm getting crash elsewhere. -O1 fixes the issue . Here are the logs https://drive.google.com/open?id=0BzoBQPp1Gv3MLXlnWnM2RzNTczQ . I'm using same input apk

@deephole
Copy link
Author

deephole commented Sep 8, 2017

justinjhendrick should I open this as a separate issue?

@justinjhendrick
Copy link
Contributor

justinjhendrick commented Sep 8, 2017

Thanks for the suggestion but I'd say that's not necessary. It's effectively the same issue. Recursing through a CFG that's too large.

@justinjhendrick
Copy link
Contributor

We'd rather not disallow recursion on CFGs given how useful it is. Do you think you could increase the stack size on your machine?

Does this reproduce without ASan? I've heard ASan limits stack size.
What is the output of ulimit -s on this machine?
Does adding the linker flag -stack_size <some_large_number> change anything?
It looks like std::thread spawns with 512KB of stack with no option for editing it. We may want to move to another cross platform thread library (boost?) so we can alter the stack size.

@minjang
Copy link
Contributor

minjang commented Sep 8, 2017

@deephole We will review changing the stack size option in our official build. But meanwhile, you may override stack size. I was able to avoid this stack overflow problem by increasing the stack size to 8MB or 16MB. Please refer to https://developer.apple.com/library/content/qa/qa1419/_index.html or https://stackoverflow.com/questions/18909395/how-do-i-increase-the-stack-size-when-compiling-with-clang-on-os-x

@deephole
Copy link
Author

deephole commented Sep 9, 2017

Answering to your questions:
ulimit is 8192
This does reproduce without ASAN as well, but takes slightly longer. I'll try increasing stack_size. Thank you for the suggestion

@deephole
Copy link
Author

I can confirm that increasing stack size via -stack_size linker flag helped me. Thank you!

@minjang minjang closed this as completed Sep 11, 2017
@deephole
Copy link
Author

deephole commented Sep 12, 2017

Fix which worked for me using boost if anybody is interested:

@@ -16,7 +16,8 @@
 #include <mutex>
 #include <queue>
 #include <random>
-#include <thread>
+//#include <thread>
+#include "boost/thread.hpp"
 
 namespace workqueue_impl {
 
@@ -121,7 +122,7 @@
 WorkQueue<Input, std::nullptr_t /*Data*/, std::nullptr_t /*Output*/>
 workqueue_foreach(
     const std::function<void(Input)>& func,
-    unsigned int num_threads = std::thread::hardware_concurrency()) {
+    unsigned int num_threads = boost::thread::hardware_concurrency()) {
   using Data = std::nullptr_t;
   using Output = std::nullptr_t;
   return WorkQueue<Input, Data, Output>(
@@ -142,7 +143,7 @@
 WorkQueue<Input, std::nullptr_t /*Data*/, Output> workqueue_mapreduce(
     const std::function<Output(Input)>& mapper,
     const std::function<Output(Output, Output)>& reducer,
-    unsigned int num_threads = std::thread::hardware_concurrency()) {
+    unsigned int num_threads = boost::thread::hardware_concurrency()) {
   using Data = std::nullptr_t;
   return WorkQueue<Input, Data, Output>(
       [mapper](Data&, Input a) -> Output { return mapper(a); },
@@ -170,7 +171,7 @@
 template <class Input, class Data, class Output>
 Output WorkQueue<Input, Data, Output>::run_all(const Output& init_output) {
   m_currently_running = true;
-  std::vector<std::thread> all_threads;
+  std::vector<boost::thread> all_threads;
   auto worker = [&](WorkerState<Input, Data, Output>* state, size_t state_idx) {
     state->result = init_output;
     auto attempts =
@@ -192,8 +193,11 @@
     }
   };
 
+  boost::thread::attributes attrs;
+  attrs.set_stack_size(4096*500);
+
   for (size_t i = 0; i < m_num_threads; ++i) {
-    all_threads.emplace_back(worker, m_states[i].get(), i);
+    all_threads.emplace_back(attrs, boost::bind<void>(worker, m_states[i].get(), i));
   }
 
   for (auto& thread : all_threads) {

@justinjhendrick
Copy link
Contributor

justinjhendrick commented Sep 12, 2017

@deephole, would you like to make a pull request to switch from std::thread to boost::thread?

If you'd like to make the pull request, this is a great start. There are a few more files that would need editing: test/unit/TraceMultithreadingTest.cpp, libredex/Parallelwalkers.h, test/unit/WorkQueuePerfTest.cpp. Also, we'd prefer a named constant const std::size_t TWO_MEGABYTES = 4096 * 500 as a member of work queue.

@deephole
Copy link
Author

Thank you. I might do it

@justinjhendrick
Copy link
Contributor

Another thing: you can tell ASAN to ignore deeply recursive functions like this:

Create a file named asan_ignore.txt containing fun:*visit* and pass -fsanitize-blacklist=asan_ignore.txt at compile and link time

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants