(List (= scope= flags=0 words=[] bindings=[('HERE', {[DQ [ComSub (AndOr OP_AND_IF (Com {[LIT_CHARS cd]} {[DQ [ComSub (Com {[LIT_CHARS dirname]} {[DQ [VarSub 0]]})]]}) (Com {[LIT_CHARS pwd]}) )]]})]) (= scope= flags=0 words=[] bindings=[('revert', {[LIT_CHARS no]})]) (= scope= flags=0 words=[] bindings=[('extra_options', {[SQ ]})]) (= scope= flags=0 words=[] bindings=[('device', {[SQ ]})]) (= scope= flags=0 words=[] bindings=[('lib', {[SQ ]})]) (FunctionDef usage [] (List (Com {[LIT_CHARS echo]} {[DQ [LIT_CHARS "usage: "][VarSub 0][LIT_CHARS " [--revert] [--device device-id] [--lib path] [--extra_options options]"]]}) (Com {[LIT_CHARS echo]} {[DQ [LIT_CHARS " --revert: Uninstall ASan from the device."]]}) (Com {[LIT_CHARS echo]} {[DQ [LIT_CHARS " --lib: Path to ASan runtime library."]]}) (Com {[LIT_CHARS echo]} {[DQ [LIT_CHARS " --extra_options: Extra ASAN_OPTIONS."]]}) (Com {[LIT_CHARS echo]} {[DQ [LIT_CHARS " --device: Install to the given device. Use 'adb devices' to find"]]}) (Com {[LIT_CHARS echo]} {[DQ [LIT_CHARS " device-id."]]}) (Com {[LIT_CHARS echo]}) (Com {[LIT_CHARS exit]} {[LIT_CHARS 1]}) ) ) (While (DBracket {B2 BINARY_STRING_GREAT {[VarSub #]} {[LIT_CHARS 0]}}) (List (Case to_match={[VarSub 1]}, pat_word_list=[[{[LIT_CHARS --revert]}], [{[LIT_CHARS --extra-options]}], [{[LIT_CHARS --lib]}], [{[LIT_CHARS --device]}], [{[LIT_OTHER "*"]}]] (= scope= flags=0 words=[] bindings=[('revert', {[LIT_CHARS yes]})]) (List (Com {[LIT_CHARS shift]}) (If (DBracket {B2 BINARY_STRING_EQUAL {[VarSub #]} {[LIT_CHARS 0]}}) (List (Com {[LIT_CHARS echo]} {[DQ [LIT_CHARS "--extra-options requires an argument."]]}) (Com {[LIT_CHARS exit]} {[LIT_CHARS 1]}) ) ) (= scope= flags=0 words=[] bindings=[('extra_options', {[DQ [VarSub 1]]})]) ) (List (Com {[LIT_CHARS shift]}) (If (DBracket {B2 BINARY_STRING_EQUAL {[VarSub #]} {[LIT_CHARS 0]}}) (List (Com {[LIT_CHARS echo]} {[DQ [LIT_CHARS "--lib requires an argument."]]}) (Com {[LIT_CHARS exit]} {[LIT_CHARS 1]}) ) ) (= scope= flags=0 words=[] bindings=[('lib', {[DQ [VarSub 1]]})]) ) (List (Com {[LIT_CHARS shift]}) (If (DBracket {B2 BINARY_STRING_EQUAL {[VarSub #]} {[LIT_CHARS 0]}}) (List (Com {[LIT_CHARS echo]} {[DQ [LIT_CHARS "--device requires an argument."]]}) (Com {[LIT_CHARS exit]} {[LIT_CHARS 1]}) ) ) (= scope= flags=0 words=[] bindings=[('device', {[DQ [VarSub 1]]})]) ) (Com {[LIT_CHARS usage]}) ) (Com {[LIT_CHARS shift]}) ) ) (= scope= flags=0 words=[] bindings=[('ADB', {[VarSub ADB test_op=VS_TEST_COLON_HYPHEN {[LIT_CHARS adb]}]})]) (If (DBracket {B2 BINARY_STRING_NOT_EQUAL {[LIT_CHARS x] [VarSub device]} {[LIT_CHARS x]}}) (= scope= flags=0 words=[] bindings=[('ADB', {[DQ [VarSub ADB][LIT_CHARS " -s "][VarSub device]]})]) ) (= scope= flags=0 words=[] bindings=[('ASAN_RT', {[DQ [LIT_CHARS libclang_rt.asan-arm-android.so]]})]) (If (DBracket {B2 BINARY_STRING_EQUAL {[LIT_CHARS x] [VarSub revert]} {[LIT_CHARS xyes]}}) (List (Com {[LIT_CHARS echo]} {[SQ > Uninstalling ASan">]}) (Com {[VarSub ADB]} {[LIT_CHARS root]}) (Com {[VarSub ADB]} {[LIT_CHARS wait-for-device]}) (Com {[VarSub ADB]} {[LIT_CHARS remount]}) (Com {[VarSub ADB]} {[LIT_CHARS shell]} {[LIT_CHARS mv]} {[LIT_CHARS /system/bin/app_process.real]} {[LIT_CHARS /system/bin/app_process]}) (Com {[VarSub ADB]} {[LIT_CHARS shell]} {[LIT_CHARS rm]} {[LIT_CHARS /system/bin/asanwrapper]}) (Com {[VarSub ADB]} {[LIT_CHARS shell]} {[LIT_CHARS rm]} {[LIT_CHARS /system/lib/] [VarSub ASAN_RT]}) (Com {[LIT_CHARS echo]} {[SQ > Restarting shell">]}) (Com {[VarSub ADB]} {[LIT_CHARS shell]} {[LIT_CHARS stop]}) (Com {[VarSub ADB]} {[LIT_CHARS shell]} {[LIT_CHARS start]}) (Com {[LIT_CHARS echo]} {[SQ > Done">]}) (Com {[LIT_CHARS exit]} {[LIT_CHARS 0]}) ) ) (If (DBracket {B1 UNARY_FILE_d {[DQ [VarSub lib]]}}) (= scope= flags=0 words=[] bindings=[('ASAN_RT_PATH', {[DQ [VarSub lib]]})]) (DBracket {B? LOGICAL_BINARY_AND {B1 UNARY_FILE_f {[DQ [VarSub lib]]}} {B2 BINARY_STRING_EQUAL {[DQ [VarSub lib]]} {[LIT_OTHER "*"] [DQ [VarSub ASAN_RT]]}}}) (= scope= flags=0 words=[] bindings=[('ASAN_RT_PATH', {[ComSub (Com {[LIT_CHARS dirname]} {[DQ [VarSub lib]]})]})]) (DBracket {B1 UNARY_FILE_f {[DQ [VarSub HERE][LIT_CHARS /][VarSub ASAN_RT]]}}) (= scope= flags=0 words=[] bindings=[('ASAN_RT_PATH', {[DQ [VarSub HERE]]})]) (DBracket {B2 BINARY_STRING_EQUAL {[ComSub (Com {[LIT_CHARS basename]} {[DQ [VarSub HERE]]})]} {[DQ [LIT_CHARS bin]]}}) (List (= scope= flags=0 words=[] bindings=[('P', {[ComSub (Pipeline (Com redirects=[(FilenameRedirectNode filename={[LIT_CHARS /dev/null]} "> 2)]{[LIT_CHARS ls]} {[DQ [VarSub HERE]] [LIT_CHARS /../lib/] [DQ [VarSub ASAN_RT]]} {[DQ [VarSub HERE]] [LIT_CHARS /../lib/clang/] [LIT_OTHER "*"] [LIT_CHARS /lib/linux/] [DQ [VarSub ASAN_RT]]}) (Com {[LIT_CHARS sort]}) (Com {[LIT_CHARS tail]} {[LIT_CHARS -1]}) )]})]) (If (DBracket {B1 UNARY_STRING_n {[DQ [VarSub P]]}}) (= scope= flags=0 words=[] bindings=[('ASAN_RT_PATH', {[DQ [ComSub (Com {[LIT_CHARS dirname]} {[DQ [VarSub P]]})]]})]) ) ) ) (If (DBracket {B? LOGICAL_BINARY_OR {B1 UNARY_STRING_z {[DQ [VarSub ASAN_RT_PATH]]}} {B! {B1 UNARY_FILE_f {[DQ [VarSub ASAN_RT_PATH][LIT_CHARS /][VarSub ASAN_RT]]}}}}) (List (Com {[LIT_CHARS echo]} {[DQ [LIT_CHARS "ASan runtime library not found"]]}) (Com {[LIT_CHARS exit]} {[LIT_CHARS 1]}) ) ) (= scope= flags=0 words=[] bindings=[('TMPDIRBASE', {[ComSub (Com {[LIT_CHARS mktemp]} {[LIT_CHARS -d]})]})]) (= scope= flags=0 words=[] bindings=[('TMPDIROLD', {[DQ [VarSub TMPDIRBASE][LIT_CHARS /old]]})]) (= scope= flags=0 words=[] bindings=[('TMPDIR', {[DQ [VarSub TMPDIRBASE][LIT_CHARS /new]]})]) (Com {[LIT_CHARS mkdir]} {[DQ [VarSub TMPDIROLD]]}) (Com {[LIT_CHARS echo]} {[SQ > Remounting /system rw">]}) (Com {[VarSub ADB]} {[LIT_CHARS root]}) (Com {[VarSub ADB]} {[LIT_CHARS wait-for-device]}) (Com {[VarSub ADB]} {[LIT_CHARS remount]}) (Com {[LIT_CHARS echo]} {[SQ > Copying files from the device">]}) (Com {[VarSub ADB]} {[LIT_CHARS pull]} {[LIT_CHARS /system/bin/app_process]} {[DQ [VarSub TMPDIROLD]]}) (AndOr OP_OR_IF (Com {[VarSub ADB]} {[LIT_CHARS pull]} {[LIT_CHARS /system/bin/app_process.real]} {[DQ [VarSub TMPDIROLD]]}) (Com {[LIT_CHARS true]}) ) (AndOr OP_OR_IF (Com {[VarSub ADB]} {[LIT_CHARS pull]} {[LIT_CHARS /system/bin/asanwrapper]} {[DQ [VarSub TMPDIROLD]]}) (Com {[LIT_CHARS true]}) ) (AndOr OP_OR_IF (Com {[VarSub ADB]} {[LIT_CHARS pull]} {[LIT_CHARS /system/lib/libclang_rt.asan-arm-android.so]} {[DQ [VarSub TMPDIROLD]]}) (Com {[LIT_CHARS true]}) ) (Com {[LIT_CHARS cp]} {[LIT_CHARS -r]} {[DQ [VarSub TMPDIROLD]]} {[DQ [VarSub TMPDIR]]}) (If (Pipeline! (DBracket {B1 UNARY_FILE_f {[DQ [VarSub TMPDIR][LIT_CHARS /app_process]]}}) ) (List (Com {[LIT_CHARS echo]} {[DQ [LIT_CHARS "app_process missing???"]]}) (Com {[LIT_CHARS exit]} {[LIT_CHARS 1]}) ) ) (If (DBracket {B1 UNARY_FILE_f {[DQ [VarSub TMPDIR][LIT_CHARS /app_process.real]]}}) (Com {[LIT_CHARS echo]} {[DQ [LIT_CHARS "app_process.real exists, updating the wrapper"]]}) (ElseTrue) (List (Com {[LIT_CHARS echo]} {[DQ [LIT_CHARS "app_process.real missing, new installation"]]}) (Com {[LIT_CHARS mv]} {[DQ [VarSub TMPDIR][LIT_CHARS /app_process]]} {[DQ [VarSub TMPDIR][LIT_CHARS /app_process.real]]}) ) ) (Com {[LIT_CHARS echo]} {[SQ > Generating wrappers">]}) (Com {[LIT_CHARS cp]} {[DQ [VarSub ASAN_RT_PATH][LIT_CHARS /][VarSub ASAN_RT]]} {[DQ [VarSub TMPDIR][LIT_CHARS /]]}) (= scope= flags=0 words=[] bindings=[('ASAN_OPTIONS', {[LIT_VAR_LIKE "start_deactivated="] [LIT_CHARS 1] [LIT_COMMA ","] [LIT_VAR_LIKE "alloc_dealloc_mismatch="] [LIT_CHARS 0] =})]) (If (DBracket {B2 BINARY_STRING_NOT_EQUAL {[LIT_CHARS x] [VarSub extra_options]} {[LIT_CHARS x]}}) (= scope= flags=0 words=[] bindings=[('ASAN_OPTIONS', {[DQ [VarSub ASAN_OPTIONS][LIT_CHARS ","][VarSub extra_options]]})]) ) (Com {[LIT_CHARS cat]} < (HereDocRedirectNode here_end='EOF' do_expansion=True body_word={[DQ [LIT_CHARS "#!/system/bin/sh\n"][LIT_CHARS "ASAN_OPTIONS="][VarSub ASAN_OPTIONS][LIT_CHARS " "][\ LIT_ESCAPED_CHAR "\\\\"][LIT_CHARS "\n"][LIT_CHARS "LD_PRELOAD=libclang_rt.asan-arm-android.so "][\ LIT_ESCAPED_CHAR "\\\\"][LIT_CHARS "\n"][LIT_CHARS "exec /system/bin/app_process.real "][\ LIT_ESCAPED_CHAR "\\$"][LIT_CHARS "@\n"][LIT_CHARS "\n"]]} 0), (FilenameRedirectNode filename={[DQ [VarSub TMPDIR][LIT_CHARS /app_process]]} "> 1), > ) (Com {[LIT_CHARS cat]} < (HereDocRedirectNode here_end='EOF' do_expansion=True body_word={[DQ [LIT_CHARS "#!/system/bin/sh\n"][LIT_CHARS "LD_PRELOAD=libclang_rt.asan-arm-android.so "][\ LIT_ESCAPED_CHAR "\\\\"][LIT_CHARS "\n"][LIT_CHARS "exec "][\ LIT_ESCAPED_CHAR "\\$"][LIT_CHARS "@\n"][LIT_CHARS "\n"]]} 0), (FilenameRedirectNode filename={[DQ [VarSub TMPDIR][LIT_CHARS /asanwrapper]]} "> 1), > ) (If (Pipeline! (Subshell (AndOr OP_AND_IF (Com {[LIT_CHARS cd]} {[DQ [VarSub TMPDIRBASE]]}) (Com {[LIT_CHARS diff]} {[LIT_CHARS -qr]} {[LIT_CHARS old/]} {[LIT_CHARS new/]}) ) ) ) (List (Com {[LIT_CHARS echo]} {[SQ > Pushing files to the device">]}) (Com {[VarSub ADB]} {[LIT_CHARS push]} {[DQ [VarSub TMPDIR][LIT_CHARS /][VarSub ASAN_RT]]} {[LIT_CHARS /system/lib/]}) (Com {[VarSub ADB]} {[LIT_CHARS push]} {[DQ [VarSub TMPDIR][LIT_CHARS /app_process]]} {[LIT_CHARS /system/bin/app_process]}) (Com {[VarSub ADB]} {[LIT_CHARS push]} {[DQ [VarSub TMPDIR][LIT_CHARS /app_process.real]]} {[LIT_CHARS /system/bin/app_process.real]}) (Com {[VarSub ADB]} {[LIT_CHARS push]} {[DQ [VarSub TMPDIR][LIT_CHARS /asanwrapper]]} {[LIT_CHARS /system/bin/asanwrapper]}) (Com {[VarSub ADB]} {[LIT_CHARS shell]} {[LIT_CHARS chown]} {[LIT_CHARS root.shell]} {[LIT_CHARS /system/bin/app_process]} {[LIT_CHARS /system/bin/app_process.real]} {[LIT_CHARS /system/bin/asanwrapper]}) (Com {[VarSub ADB]} {[LIT_CHARS shell]} {[LIT_CHARS chmod]} {[LIT_CHARS 755]} {[LIT_CHARS /system/bin/app_process]} {[LIT_CHARS /system/bin/app_process.real]} {[LIT_CHARS /system/bin/asanwrapper]}) (Com {[LIT_CHARS echo]} {[SQ > Restarting shell (asynchronous)">]}) (Com {[VarSub ADB]} {[LIT_CHARS shell]} {[LIT_CHARS stop]}) (Com {[VarSub ADB]} {[LIT_CHARS shell]} {[LIT_CHARS start]}) (Com {[LIT_CHARS echo]} {[SQ > Please wait until the device restarts">]}) ) (ElseTrue) (Com {[LIT_CHARS echo]} {[SQ > Device is up to date">]}) ) (Com {[LIT_CHARS rm]} {[LIT_CHARS -r]} {[DQ [VarSub TMPDIRBASE]]}) )