xref: /aosp_15_r20/tools/security/gdb/parameters_extract.py (revision d9ecfb0f4d734c9ce41cde8ac4d585b094fd4222)
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