1*d9ecfb0fSAndroid Build Coastguard Workerimport os 2*d9ecfb0fSAndroid Build Coastguard Workerimport re 3*d9ecfb0fSAndroid Build Coastguard Worker 4*d9ecfb0fSAndroid Build Coastguard Worker# If doing it on device with gdbserver 5*d9ecfb0fSAndroid Build Coastguard WorkerDEVICE = os.environ.get('GDBSCRIPT_ON_DEVICE', False) 6*d9ecfb0fSAndroid Build Coastguard Worker# Path of the file on device 7*d9ecfb0fSAndroid Build Coastguard WorkerDEVICE_FILEPATH = os.environ.get('GDBSCRIPT_FILENAME', None) 8*d9ecfb0fSAndroid Build Coastguard Worker# GDBServer's port 9*d9ecfb0fSAndroid Build Coastguard WorkerDEVICE_PORT = os.environ.get('GDBSCRIPT_DEVICE_PORT', 4444) 10*d9ecfb0fSAndroid Build Coastguard Worker# Serial number of device for adb 11*d9ecfb0fSAndroid Build Coastguard WorkerDEVICE_SERIAL = os.environ.get('GDBSCRIPT_DEVICE_SERIAL', None) 12*d9ecfb0fSAndroid Build Coastguard Worker 13*d9ecfb0fSAndroid Build Coastguard Workerdef check_device_args(): 14*d9ecfb0fSAndroid Build Coastguard Worker """ 15*d9ecfb0fSAndroid Build Coastguard Worker Checks if FILEPATH is provided if the execution is on device 16*d9ecfb0fSAndroid Build Coastguard Worker """ 17*d9ecfb0fSAndroid Build Coastguard Worker if not DEVICE: 18*d9ecfb0fSAndroid Build Coastguard Worker return 19*d9ecfb0fSAndroid Build Coastguard Worker 20*d9ecfb0fSAndroid Build Coastguard Worker if not DEVICE_FILEPATH: 21*d9ecfb0fSAndroid Build Coastguard Worker raise ValueError("Filename (GDBSCRIPT_FILEPATH) not provided") 22*d9ecfb0fSAndroid Build Coastguard Worker 23*d9ecfb0fSAndroid Build Coastguard Workerclass RecordPoint(gdb.Breakpoint): 24*d9ecfb0fSAndroid Build Coastguard Worker """ 25*d9ecfb0fSAndroid Build Coastguard Worker A custom breakpoint that records the arguments when the breakpoint is hit and continues 26*d9ecfb0fSAndroid Build Coastguard Worker Also enables the next breakpoint and disables all the ones after it 27*d9ecfb0fSAndroid Build Coastguard Worker """ 28*d9ecfb0fSAndroid Build Coastguard Worker def stop(self): 29*d9ecfb0fSAndroid Build Coastguard Worker """ 30*d9ecfb0fSAndroid Build Coastguard Worker The function that's called when a breakpoint is hit. If we return true, 31*d9ecfb0fSAndroid Build Coastguard Worker it halts otherwise it continues 32*d9ecfb0fSAndroid Build Coastguard Worker We always return false because we just need to record the value and we 33*d9ecfb0fSAndroid Build Coastguard Worker can do it without halting the program 34*d9ecfb0fSAndroid Build Coastguard Worker """ 35*d9ecfb0fSAndroid Build Coastguard Worker self.args[self.times_hit % self.count] = get_function_args() 36*d9ecfb0fSAndroid Build Coastguard Worker self.times_hit += 1 37*d9ecfb0fSAndroid Build Coastguard Worker 38*d9ecfb0fSAndroid Build Coastguard Worker if self.next_bp != None: 39*d9ecfb0fSAndroid Build Coastguard Worker self.next_bp.previous_hit() 40*d9ecfb0fSAndroid Build Coastguard Worker 41*d9ecfb0fSAndroid Build Coastguard Worker return False 42*d9ecfb0fSAndroid Build Coastguard Worker 43*d9ecfb0fSAndroid Build Coastguard Worker def previous_hit(self): 44*d9ecfb0fSAndroid Build Coastguard Worker """ 45*d9ecfb0fSAndroid Build Coastguard Worker This function is called if the previous breakpoint is hit so it can enable 46*d9ecfb0fSAndroid Build Coastguard Worker itself and disable the next ones 47*d9ecfb0fSAndroid Build Coastguard Worker """ 48*d9ecfb0fSAndroid Build Coastguard Worker self.enabled = True 49*d9ecfb0fSAndroid Build Coastguard Worker 50*d9ecfb0fSAndroid Build Coastguard Worker if self.next_bp != None: 51*d9ecfb0fSAndroid Build Coastguard Worker self.next_bp.propagate_disable() 52*d9ecfb0fSAndroid Build Coastguard Worker 53*d9ecfb0fSAndroid Build Coastguard Worker def propagate_disable(self): 54*d9ecfb0fSAndroid Build Coastguard Worker """ 55*d9ecfb0fSAndroid Build Coastguard Worker Disabled all the breakpoints after itself 56*d9ecfb0fSAndroid Build Coastguard Worker """ 57*d9ecfb0fSAndroid Build Coastguard Worker self.enabled = False 58*d9ecfb0fSAndroid Build Coastguard Worker if self.next_bp != None: 59*d9ecfb0fSAndroid Build Coastguard Worker self.next_bp.propagate_disable() 60*d9ecfb0fSAndroid Build Coastguard Worker 61*d9ecfb0fSAndroid Build Coastguard Worker def process_arguments(self): 62*d9ecfb0fSAndroid Build Coastguard Worker """ 63*d9ecfb0fSAndroid Build Coastguard Worker Orders the recorded arguments into the right order (oldest to newest) 64*d9ecfb0fSAndroid Build Coastguard Worker """ 65*d9ecfb0fSAndroid Build Coastguard Worker current_hit_point = self.times_hit % self.count 66*d9ecfb0fSAndroid Build Coastguard Worker # Split at the point of current_hit_point because all the entries after it 67*d9ecfb0fSAndroid Build Coastguard Worker # are older than the ones before it 68*d9ecfb0fSAndroid Build Coastguard Worker self.processed_args = self.args[current_hit_point:] + self.args[:current_hit_point] 69*d9ecfb0fSAndroid Build Coastguard Worker self.current_arg_idx = 0 70*d9ecfb0fSAndroid Build Coastguard Worker 71*d9ecfb0fSAndroid Build Coastguard Worker def get_arguments(self): 72*d9ecfb0fSAndroid Build Coastguard Worker """ 73*d9ecfb0fSAndroid Build Coastguard Worker Gets the current argument value. 74*d9ecfb0fSAndroid Build Coastguard Worker Should be called the same amount of times as the function was called 75*d9ecfb0fSAndroid Build Coastguard Worker in the stacktrace 76*d9ecfb0fSAndroid Build Coastguard Worker First call returns the arguments recorded for the first call in the stacktrace 77*d9ecfb0fSAndroid Build Coastguard Worker and so on. 78*d9ecfb0fSAndroid Build Coastguard Worker """ 79*d9ecfb0fSAndroid Build Coastguard Worker if self.current_arg_idx >= len(self.processed_args): 80*d9ecfb0fSAndroid Build Coastguard Worker raise ValueError("Cannot get arguments more times than the function \ 81*d9ecfb0fSAndroid Build Coastguard Worker was present in stacktrace") 82*d9ecfb0fSAndroid Build Coastguard Worker 83*d9ecfb0fSAndroid Build Coastguard Worker cur = self.processed_args[self.current_arg_idx] 84*d9ecfb0fSAndroid Build Coastguard Worker self.current_arg_idx += 1 85*d9ecfb0fSAndroid Build Coastguard Worker return cur 86*d9ecfb0fSAndroid Build Coastguard Worker 87*d9ecfb0fSAndroid Build Coastguard Workerdef init_gdb(): 88*d9ecfb0fSAndroid Build Coastguard Worker """ 89*d9ecfb0fSAndroid Build Coastguard Worker Initialized the GDB specific stuff 90*d9ecfb0fSAndroid Build Coastguard Worker """ 91*d9ecfb0fSAndroid Build Coastguard Worker gdb.execute('set pagination off') 92*d9ecfb0fSAndroid Build Coastguard Worker gdb.execute('set print frame-arguments all') 93*d9ecfb0fSAndroid Build Coastguard Worker if DEVICE: 94*d9ecfb0fSAndroid Build Coastguard Worker gdb.execute('target extended-remote :{}'.format(DEVICE_PORT)) 95*d9ecfb0fSAndroid Build Coastguard Worker gdb.execute('set remote exec-file /data/local/tmp/{}'.format(DEVICE_FILEPATH)) 96*d9ecfb0fSAndroid Build Coastguard Worker 97*d9ecfb0fSAndroid Build Coastguard Workerdef initial_run(): 98*d9ecfb0fSAndroid Build Coastguard Worker """ 99*d9ecfb0fSAndroid Build Coastguard Worker The initial run of the program which captures the stacktrace in init.log file 100*d9ecfb0fSAndroid Build Coastguard Worker """ 101*d9ecfb0fSAndroid Build Coastguard Worker gdb.execute('r > init.log 2>&1',from_tty=True, to_string=True) 102*d9ecfb0fSAndroid Build Coastguard Worker if DEVICE: 103*d9ecfb0fSAndroid Build Coastguard Worker if DEVICE_SERIAL: 104*d9ecfb0fSAndroid Build Coastguard Worker os.system('adb -s "{}" pull /data/local/tmp/init.log'.format(DEVICE_SERIAL)) 105*d9ecfb0fSAndroid Build Coastguard Worker else: 106*d9ecfb0fSAndroid Build Coastguard Worker os.system("adb pull /data/local/tmp/init.log") 107*d9ecfb0fSAndroid Build Coastguard Worker with open("init.log", "rb") as f: 108*d9ecfb0fSAndroid Build Coastguard Worker out = f.read().decode() 109*d9ecfb0fSAndroid Build Coastguard Worker return out 110*d9ecfb0fSAndroid Build Coastguard Worker 111*d9ecfb0fSAndroid Build Coastguard Workerdef gdb_exit(): 112*d9ecfb0fSAndroid Build Coastguard Worker """ 113*d9ecfb0fSAndroid Build Coastguard Worker Exits the GDB instance 114*d9ecfb0fSAndroid Build Coastguard Worker """ 115*d9ecfb0fSAndroid Build Coastguard Worker gdb.execute('q') 116*d9ecfb0fSAndroid Build Coastguard Worker 117*d9ecfb0fSAndroid Build Coastguard Workerdef get_stacktrace_functions(stacktrace): 118*d9ecfb0fSAndroid Build Coastguard Worker """ 119*d9ecfb0fSAndroid Build Coastguard Worker Gets the functions from ASAN/HWASAN's stacktrace 120*d9ecfb0fSAndroid Build Coastguard Worker Args: 121*d9ecfb0fSAndroid Build Coastguard Worker stacktrace: (string) ASAN/HWASAN's stacktrace output 122*d9ecfb0fSAndroid Build Coastguard Worker Returns: 123*d9ecfb0fSAndroid Build Coastguard Worker functions: (list) functions in the stacktrace 124*d9ecfb0fSAndroid Build Coastguard Worker """ 125*d9ecfb0fSAndroid Build Coastguard Worker stacktrace_start = stacktrace[stacktrace.index('==ERROR: '):].split("\n") 126*d9ecfb0fSAndroid Build Coastguard Worker functions = [] 127*d9ecfb0fSAndroid Build Coastguard Worker 128*d9ecfb0fSAndroid Build Coastguard Worker # skip the first two lines of stacktrace 129*d9ecfb0fSAndroid Build Coastguard Worker for line in stacktrace_start[2:]: 130*d9ecfb0fSAndroid Build Coastguard Worker if line == "": 131*d9ecfb0fSAndroid Build Coastguard Worker break 132*d9ecfb0fSAndroid Build Coastguard Worker 133*d9ecfb0fSAndroid Build Coastguard Worker # Extracts the function name from a line like this 134*d9ecfb0fSAndroid Build Coastguard Worker # "#0 0xaddress in function_name() file/path.cc:xx:yy" 135*d9ecfb0fSAndroid Build Coastguard Worker func_name = line.strip().split(" ")[3] 136*d9ecfb0fSAndroid Build Coastguard Worker if '(' in func_name: 137*d9ecfb0fSAndroid Build Coastguard Worker func_name = func_name[:func_name.index('(')] 138*d9ecfb0fSAndroid Build Coastguard Worker 139*d9ecfb0fSAndroid Build Coastguard Worker functions.append(func_name) 140*d9ecfb0fSAndroid Build Coastguard Worker 141*d9ecfb0fSAndroid Build Coastguard Worker #remove last function from stacktrace because it would be _start 142*d9ecfb0fSAndroid Build Coastguard Worker return functions 143*d9ecfb0fSAndroid Build Coastguard Worker 144*d9ecfb0fSAndroid Build Coastguard Workerdef parse_function_arguments(func_info): 145*d9ecfb0fSAndroid Build Coastguard Worker """ 146*d9ecfb0fSAndroid Build Coastguard Worker Parses the output of 'whatis' command into a list of arguments 147*d9ecfb0fSAndroid Build Coastguard Worker "void (teststruct)" --> ["teststruct"] 148*d9ecfb0fSAndroid Build Coastguard Worker "int (int (*)(int, char **, char **), int, char **, int (*)(int, char **, char **), 149*d9ecfb0fSAndroid Build Coastguard Worker void (*)(void), void (*)(void), void *)" --> ['int (*)(int, char **, char **)', 150*d9ecfb0fSAndroid Build Coastguard Worker 'int', 'char **', 'int (*)(int, char **, char **)', 'void (*)(void)', 151*d9ecfb0fSAndroid Build Coastguard Worker 'void (*)(void)', ' void *'] 152*d9ecfb0fSAndroid Build Coastguard Worker 153*d9ecfb0fSAndroid Build Coastguard Worker Args: 154*d9ecfb0fSAndroid Build Coastguard Worker func_info: (string) output of gdb's 'whatis' command for a function 155*d9ecfb0fSAndroid Build Coastguard Worker Returns: 156*d9ecfb0fSAndroid Build Coastguard Worker parsed_params: (list) parsed parameters of the function 157*d9ecfb0fSAndroid Build Coastguard Worker """ 158*d9ecfb0fSAndroid Build Coastguard Worker if '(' not in func_info: 159*d9ecfb0fSAndroid Build Coastguard Worker return [] 160*d9ecfb0fSAndroid Build Coastguard Worker func_params = func_info[func_info.index('(')+1:-1] 161*d9ecfb0fSAndroid Build Coastguard Worker parentheses_count = 0 162*d9ecfb0fSAndroid Build Coastguard Worker current_param = "" 163*d9ecfb0fSAndroid Build Coastguard Worker parsed_params = [] 164*d9ecfb0fSAndroid Build Coastguard Worker 165*d9ecfb0fSAndroid Build Coastguard Worker for token in func_params: 166*d9ecfb0fSAndroid Build Coastguard Worker # Essentially trying to get the data types from a function declaration 167*d9ecfb0fSAndroid Build Coastguard Worker if token == '(': 168*d9ecfb0fSAndroid Build Coastguard Worker parentheses_count += 1 169*d9ecfb0fSAndroid Build Coastguard Worker elif token == ')': 170*d9ecfb0fSAndroid Build Coastguard Worker parentheses_count -= 1 171*d9ecfb0fSAndroid Build Coastguard Worker 172*d9ecfb0fSAndroid Build Coastguard Worker # If we are not inside any paren and see a ',' it signals the start of 173*d9ecfb0fSAndroid Build Coastguard Worker #the next parameter 174*d9ecfb0fSAndroid Build Coastguard Worker if token == ',' and parentheses_count == 0: 175*d9ecfb0fSAndroid Build Coastguard Worker parsed_params.append(current_param.strip()) 176*d9ecfb0fSAndroid Build Coastguard Worker current_param = "" 177*d9ecfb0fSAndroid Build Coastguard Worker else: 178*d9ecfb0fSAndroid Build Coastguard Worker current_param += token 179*d9ecfb0fSAndroid Build Coastguard Worker 180*d9ecfb0fSAndroid Build Coastguard Worker parsed_params.append(current_param) 181*d9ecfb0fSAndroid Build Coastguard Worker return parsed_params 182*d9ecfb0fSAndroid Build Coastguard Worker 183*d9ecfb0fSAndroid Build Coastguard Workerdef parse_stacktrace(stacktrace): 184*d9ecfb0fSAndroid Build Coastguard Worker """ 185*d9ecfb0fSAndroid Build Coastguard Worker Parses the ASAN/HWASAN's stacktrace to a list of functions, their addresses 186*d9ecfb0fSAndroid Build Coastguard Worker and argument types 187*d9ecfb0fSAndroid Build Coastguard Worker Args: 188*d9ecfb0fSAndroid Build Coastguard Worker stacktrace: (string) ASAN/HWASAN's stacktrace output 189*d9ecfb0fSAndroid Build Coastguard Worker Returns: 190*d9ecfb0fSAndroid Build Coastguard Worker functions_info: (list) parsed function information as a dictionary 191*d9ecfb0fSAndroid Build Coastguard Worker """ 192*d9ecfb0fSAndroid Build Coastguard Worker stacktrace_functions = get_stacktrace_functions(stacktrace)[:-1] 193*d9ecfb0fSAndroid Build Coastguard Worker functions_info = [] 194*d9ecfb0fSAndroid Build Coastguard Worker for function in stacktrace_functions: 195*d9ecfb0fSAndroid Build Coastguard Worker # Gets the value right hand side of gdb's whatis command. 196*d9ecfb0fSAndroid Build Coastguard Worker # "type = {function info}" -> "{function info}" 197*d9ecfb0fSAndroid Build Coastguard Worker func_info = gdb.execute('whatis {}'.format(function), 198*d9ecfb0fSAndroid Build Coastguard Worker to_string=True).split(' = ')[1].strip() 199*d9ecfb0fSAndroid Build Coastguard Worker # Uses gdb's x/i to print its address and parse it from hex to int 200*d9ecfb0fSAndroid Build Coastguard Worker address = int(gdb.execute("x/i {}".format(function), 201*d9ecfb0fSAndroid Build Coastguard Worker to_string=True).strip().split(" ")[0], 16) 202*d9ecfb0fSAndroid Build Coastguard Worker functions_info.append({'name': function, 'address':address, 203*d9ecfb0fSAndroid Build Coastguard Worker 'arguments' : parse_function_arguments(func_info)}) 204*d9ecfb0fSAndroid Build Coastguard Worker #In the order they are called in the execution 205*d9ecfb0fSAndroid Build Coastguard Worker return functions_info[::-1] 206*d9ecfb0fSAndroid Build Coastguard Worker 207*d9ecfb0fSAndroid Build Coastguard Workerdef get_function_args(): 208*d9ecfb0fSAndroid Build Coastguard Worker """ 209*d9ecfb0fSAndroid Build Coastguard Worker Gets the current function arguments 210*d9ecfb0fSAndroid Build Coastguard Worker """ 211*d9ecfb0fSAndroid Build Coastguard Worker args = gdb.execute('info args -q', to_string=True).strip() 212*d9ecfb0fSAndroid Build Coastguard Worker return args 213*d9ecfb0fSAndroid Build Coastguard Worker 214*d9ecfb0fSAndroid Build Coastguard Workerdef functions_to_breakpoint(parsed_functions): 215*d9ecfb0fSAndroid Build Coastguard Worker """ 216*d9ecfb0fSAndroid Build Coastguard Worker Sets the breakpoint at every function and returns a dictionary mapping the 217*d9ecfb0fSAndroid Build Coastguard Worker function to it's breakpoint 218*d9ecfb0fSAndroid Build Coastguard Worker Args: 219*d9ecfb0fSAndroid Build Coastguard Worker parsed_functions: (list) functions in the stacktrace (in the same order) as 220*d9ecfb0fSAndroid Build Coastguard Worker dictionary with "name" referring to the function name 221*d9ecfb0fSAndroid Build Coastguard Worker ({"name" : function_name}) 222*d9ecfb0fSAndroid Build Coastguard Worker Returns: 223*d9ecfb0fSAndroid Build Coastguard Worker function_breakpoints: (dictionary) maps the function name to its 224*d9ecfb0fSAndroid Build Coastguard Worker breakpoint object 225*d9ecfb0fSAndroid Build Coastguard Worker """ 226*d9ecfb0fSAndroid Build Coastguard Worker function_breakpoints = {} 227*d9ecfb0fSAndroid Build Coastguard Worker last_bp = None 228*d9ecfb0fSAndroid Build Coastguard Worker 229*d9ecfb0fSAndroid Build Coastguard Worker for function in reversed(parsed_functions): 230*d9ecfb0fSAndroid Build Coastguard Worker function_name = function['name'] 231*d9ecfb0fSAndroid Build Coastguard Worker if function_name in function_breakpoints: 232*d9ecfb0fSAndroid Build Coastguard Worker function_breakpoints[function_name].count += 1 233*d9ecfb0fSAndroid Build Coastguard Worker function_breakpoints[function_name].args.append(None) 234*d9ecfb0fSAndroid Build Coastguard Worker continue 235*d9ecfb0fSAndroid Build Coastguard Worker 236*d9ecfb0fSAndroid Build Coastguard Worker cur_bp = RecordPoint("{}".format(function_name)) 237*d9ecfb0fSAndroid Build Coastguard Worker cur_bp.count = 1 238*d9ecfb0fSAndroid Build Coastguard Worker cur_bp.times_hit = 0 239*d9ecfb0fSAndroid Build Coastguard Worker cur_bp.args = [] 240*d9ecfb0fSAndroid Build Coastguard Worker cur_bp.args.append(None) 241*d9ecfb0fSAndroid Build Coastguard Worker cur_bp.next_bp = last_bp 242*d9ecfb0fSAndroid Build Coastguard Worker 243*d9ecfb0fSAndroid Build Coastguard Worker function_breakpoints[function['name']] = cur_bp 244*d9ecfb0fSAndroid Build Coastguard Worker last_bp = cur_bp 245*d9ecfb0fSAndroid Build Coastguard Worker 246*d9ecfb0fSAndroid Build Coastguard Worker return function_breakpoints 247*d9ecfb0fSAndroid Build Coastguard Worker 248*d9ecfb0fSAndroid Build Coastguard Workerdef run(parsed_functions): 249*d9ecfb0fSAndroid Build Coastguard Worker """ 250*d9ecfb0fSAndroid Build Coastguard Worker Runs the whole thing by setting up breakpoints and printing them after 251*d9ecfb0fSAndroid Build Coastguard Worker excecution is done 252*d9ecfb0fSAndroid Build Coastguard Worker Args: 253*d9ecfb0fSAndroid Build Coastguard Worker parsed_functions: A list of functions in the stacktrace (in the same order) 254*d9ecfb0fSAndroid Build Coastguard Worker as dictionary with "name" referring to the function name 255*d9ecfb0fSAndroid Build Coastguard Worker ({"name" : function_name}) 256*d9ecfb0fSAndroid Build Coastguard Worker """ 257*d9ecfb0fSAndroid Build Coastguard Worker names = [function['name'] for function in parsed_functions] 258*d9ecfb0fSAndroid Build Coastguard Worker breakpoints = functions_to_breakpoint(parsed_functions) 259*d9ecfb0fSAndroid Build Coastguard Worker 260*d9ecfb0fSAndroid Build Coastguard Worker #Disable all breakpoints at start 261*d9ecfb0fSAndroid Build Coastguard Worker for bp in breakpoints: 262*d9ecfb0fSAndroid Build Coastguard Worker breakpoints[bp].enabled = False 263*d9ecfb0fSAndroid Build Coastguard Worker 264*d9ecfb0fSAndroid Build Coastguard Worker breakpoints[names[0]].enabled = True 265*d9ecfb0fSAndroid Build Coastguard Worker 266*d9ecfb0fSAndroid Build Coastguard Worker gdb.execute('r') 267*d9ecfb0fSAndroid Build Coastguard Worker for breakpoint in breakpoints: 268*d9ecfb0fSAndroid Build Coastguard Worker breakpoints[breakpoint].process_arguments() 269*d9ecfb0fSAndroid Build Coastguard Worker 270*d9ecfb0fSAndroid Build Coastguard Worker function_args = [] 271*d9ecfb0fSAndroid Build Coastguard Worker for name in names: 272*d9ecfb0fSAndroid Build Coastguard Worker print("-----------") 273*d9ecfb0fSAndroid Build Coastguard Worker print("Function -> {}".format(name)) 274*d9ecfb0fSAndroid Build Coastguard Worker 275*d9ecfb0fSAndroid Build Coastguard Worker function_args.append({'function':name, 276*d9ecfb0fSAndroid Build Coastguard Worker 'arguments' : breakpoints[name].get_arguments()}) 277*d9ecfb0fSAndroid Build Coastguard Worker print(function_args[-1]['arguments']) 278*d9ecfb0fSAndroid Build Coastguard Worker 279*d9ecfb0fSAndroid Build Coastguard Worker return function_args 280*d9ecfb0fSAndroid Build Coastguard Worker 281*d9ecfb0fSAndroid Build Coastguard Worker 282*d9ecfb0fSAndroid Build Coastguard Workerif __name__ == '__main__': 283*d9ecfb0fSAndroid Build Coastguard Worker check_device_args() 284*d9ecfb0fSAndroid Build Coastguard Worker init_gdb() 285*d9ecfb0fSAndroid Build Coastguard Worker initial_out = initial_run() 286*d9ecfb0fSAndroid Build Coastguard Worker function_data = parse_stacktrace(initial_out) 287*d9ecfb0fSAndroid Build Coastguard Worker run(function_data) 288*d9ecfb0fSAndroid Build Coastguard Worker gdb_exit() 289