Changes in tools/gdb/utils-gdb.py [96df7c9c:9987d79]
- File:
-
- 1 edited
-
tools/gdb/utils-gdb.py (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
-
tools/gdb/utils-gdb.py
r96df7c9c r9987d79 26 26 27 27 class ThreadInfo: 28 tid = 029 cluster = None30 value = None31 32 def __init__(self, cluster, value):33 self.cluster = cluster34 self.value = value35 36 def is_system(self):37 return False28 tid = 0 29 cluster = None 30 value = None 31 32 def __init__(self, cluster, value): 33 self.cluster = cluster 34 self.value = value 35 36 def is_system(self): 37 return False 38 38 39 39 # A named tuple representing information about a stack … … 51 51 52 52 def is_cforall(): 53 return True53 return True 54 54 55 55 def get_cfa_types(): 56 # GDB types for various structures/types in CFA57 return CfaTypes(cluster_ptr = gdb.lookup_type('struct cluster').pointer(),58 processor_ptr = gdb.lookup_type('struct processor').pointer(),59 thread_ptr = gdb.lookup_type('struct $thread').pointer(),60 int_ptr = gdb.lookup_type('int').pointer(),61 thread_state = gdb.lookup_type('enum coroutine_state'))56 # GDB types for various structures/types in CFA 57 return CfaTypes(cluster_ptr = gdb.lookup_type('struct cluster').pointer(), 58 processor_ptr = gdb.lookup_type('struct processor').pointer(), 59 thread_ptr = gdb.lookup_type('struct $thread').pointer(), 60 int_ptr = gdb.lookup_type('int').pointer(), 61 thread_state = gdb.lookup_type('enum coroutine_state')) 62 62 63 63 def get_addr(addr): 64 """65 NOTE: sketchy solution to retrieve address. There is a better solution...66 @addr: str of an address that can be in a format 0xfffff <type of the object67 at this address>68 Return: str of just the address69 """70 str_addr = str(addr)71 ending_addr_index = str_addr.find('<')72 if ending_addr_index == -1:73 return str(addr)74 return str_addr[:ending_addr_index].strip()64 """ 65 NOTE: sketchy solution to retrieve address. There is a better solution... 66 @addr: str of an address that can be in a format 0xfffff <type of the object 67 at this address> 68 Return: str of just the address 69 """ 70 str_addr = str(addr) 71 ending_addr_index = str_addr.find('<') 72 if ending_addr_index == -1: 73 return str(addr) 74 return str_addr[:ending_addr_index].strip() 75 75 76 76 def print_usage(obj): 77 print(obj.__doc__)77 print(obj.__doc__) 78 78 79 79 def parse(args): 80 """81 Split the argument list in string format, where each argument is separated82 by whitespace delimiter, to a list of arguments like argv83 @args: str of arguments84 Return:85 [] if args is an empty string86 list if args is not empty87 """88 # parse the string format of arguments and return a list of arguments89 argv = args.split(' ')90 if len(argv) == 1 and argv[0] == '':91 return []92 return argv80 """ 81 Split the argument list in string format, where each argument is separated 82 by whitespace delimiter, to a list of arguments like argv 83 @args: str of arguments 84 Return: 85 [] if args is an empty string 86 list if args is not empty 87 """ 88 # parse the string format of arguments and return a list of arguments 89 argv = args.split(' ') 90 if len(argv) == 1 and argv[0] == '': 91 return [] 92 return argv 93 93 94 94 def get_cluster_root(): 95 """96 Return: gdb.Value of globalClusters.root (is an address)97 """98 cluster_root = gdb.parse_and_eval('_X11mainClusterPS7cluster_1')99 if cluster_root.address == 0x0:100 print('No clusters, program terminated')101 return cluster_root95 """ 96 Return: gdb.Value of globalClusters.root (is an address) 97 """ 98 cluster_root = gdb.parse_and_eval('_X11mainClusterPS7cluster_1') 99 if cluster_root.address == 0x0: 100 print('No clusters, program terminated') 101 return cluster_root 102 102 103 103 def find_curr_thread(): 104 # btstr = gdb.execute('bt', to_string = True).splitlines() 105 # if len(btstr) == 0: 106 # print('error') 107 # return None 108 # return btstr[0].split('this=',1)[1].split(',')[0].split(')')[0] 109 return None 104 # btstr = gdb.execute('bt', to_string = True).splitlines() 105 # if len(btstr) == 0: 106 # print('error') 107 # return None 108 # return btstr[0].split('this=',1)[1].split(',')[0].split(')')[0] 109 return None 110 111 def all_clusters(): 112 if not is_cforall(): 113 return None 114 115 cluster_root = get_cluster_root() 116 if cluster_root.address == 0x0: 117 return 118 119 curr = cluster_root 120 ret = [curr] 121 122 while True: 123 curr = curr['_X4nodeS26__cluster____dbg_node_cltr_1']['_X4nextPS7cluster_1'] 124 if curr == cluster_root: 125 break 126 127 ret.append(curr) 128 129 return ret 130 110 131 111 132 def lookup_cluster(name = None): 112 """113 Look up a cluster given its ID114 @name: str115 Return: gdb.Value116 """117 if not is_cforall():118 return None119 120 root = get_cluster_root()121 if root.address == 0x0:122 return None123 124 if not name:125 return root126 127 # lookup for the task associated with the id128 cluster = None129 curr = root130 while True:131 if curr['_X4namePKc_1'].string() == name:132 cluster = curr.address133 break134 curr = curr['_X4nodeS26__cluster____dbg_node_cltr_1']['_X4nextPS7cluster_1']135 if curr == root or curr == 0x0:136 break137 138 if not cluster:139 print("Cannot find a cluster with the name: {}.".format(name))140 return None141 142 return cluster133 """ 134 Look up a cluster given its ID 135 @name: str 136 Return: gdb.Value 137 """ 138 if not is_cforall(): 139 return None 140 141 root = get_cluster_root() 142 if root.address == 0x0: 143 return None 144 145 if not name: 146 return root 147 148 # lookup for the task associated with the id 149 cluster = None 150 curr = root 151 while True: 152 if curr['_X4namePKc_1'].string() == name: 153 cluster = curr.address 154 break 155 curr = curr['_X4nodeS26__cluster____dbg_node_cltr_1']['_X4nextPS7cluster_1'] 156 if curr == root or curr == 0x0: 157 break 158 159 if not cluster: 160 print("Cannot find a cluster with the name: {}.".format(name)) 161 return None 162 163 return cluster 143 164 144 165 def lookup_threads_by_cluster(cluster): 145 # Iterate through a circular linked list of threads and accumulate them in an array146 threads = []147 148 cfa_t = get_cfa_types()149 root = cluster['_X7threadsS8__dllist_S7$thread__1']['_X4headPY15__TYPE_generic__1'].cast(cfa_t.thread_ptr)150 151 if root == 0x0 or root.address == 0x0:152 print('There are no tasks for cluster: {}'.format(cluster))153 return threads154 155 curr = root156 tid = 0157 sid = -1158 159 while True:160 t = ThreadInfo(cluster, curr)161 if t.is_system():162 t.tid = sid163 sid -= 1164 else:165 t.tid = tid166 tid += 1167 168 threads.append(t)169 170 curr = curr['node']['next']171 if curr == root or curr == 0x0:172 break173 174 return threads166 # Iterate through a circular linked list of threads and accumulate them in an array 167 threads = [] 168 169 cfa_t = get_cfa_types() 170 root = cluster['_X7threadsS8__dllist_S7$thread__1']['_X4headPY15__TYPE_generic__1'].cast(cfa_t.thread_ptr) 171 172 if root == 0x0 or root.address == 0x0: 173 print('There are no tasks for cluster: {}'.format(cluster)) 174 return threads 175 176 curr = root 177 tid = 0 178 sid = -1 179 180 while True: 181 t = ThreadInfo(cluster, curr) 182 if t.is_system(): 183 t.tid = sid 184 sid -= 1 185 else: 186 t.tid = tid 187 tid += 1 188 189 threads.append(t) 190 191 curr = curr['node']['next'] 192 if curr == root or curr == 0x0: 193 break 194 195 return threads 175 196 176 197 def system_thread(thread): 177 return False198 return False 178 199 179 200 def adjust_stack(pc, fp, sp): 180 # pop sp, fp, pc from global stack181 gdb.execute('set $pc = {}'.format(pc))182 gdb.execute('set $rbp = {}'.format(fp))183 gdb.execute('set $sp = {}'.format(sp))201 # pop sp, fp, pc from global stack 202 gdb.execute('set $pc = {}'.format(pc)) 203 gdb.execute('set $rbp = {}'.format(fp)) 204 gdb.execute('set $sp = {}'.format(sp)) 184 205 185 206 ############################ COMMAND IMPLEMENTATION ######################### 186 207 187 208 class Clusters(gdb.Command): 188 """Cforall: Display currently known clusters209 """Cforall: Display currently known clusters 189 210 Usage: 190 info clusters : print out all the clusters211 info clusters : print out all the clusters 191 212 """ 192 213 193 def __init__(self): 194 super(Clusters, self).__init__('info clusters', gdb.COMMAND_USER) 195 196 def print_cluster(self, cluster_name, cluster_address): 197 print('{:>20} {:>20}'.format(cluster_name, cluster_address)) 198 199 #entry point from gdb 200 def invoke(self, arg, from_tty): 201 if not is_cforall(): 202 return 203 204 if arg: 205 print("info clusters does not take arguments") 206 print_usage(self) 207 return 208 209 cluster_root = get_cluster_root() 210 if cluster_root.address == 0x0: 211 return 212 213 curr = cluster_root 214 self.print_cluster('Name', 'Address') 215 216 while True: 217 self.print_cluster(curr['_X4namePKc_1'].string(), str(curr)) 218 curr = curr['_X4nodeS26__cluster____dbg_node_cltr_1']['_X4nextPS7cluster_1'] 219 if curr == cluster_root: 220 break 221 222 print("") 214 def __init__(self): 215 super(Clusters, self).__init__('info clusters', gdb.COMMAND_USER) 216 217 def print_cluster(self, cluster_name, cluster_address): 218 print('{:>20} {:>20}'.format(cluster_name, cluster_address)) 219 220 #entry point from gdb 221 def invoke(self, arg, from_tty): 222 if not is_cforall(): 223 return 224 225 if arg: 226 print("info clusters does not take arguments") 227 print_usage(self) 228 return 229 230 self.print_cluster('Name', 'Address') 231 232 for c in all_clusters(): 233 self.print_cluster(c['_X4namePKc_1'].string(), str(c)) 234 235 print("") 223 236 224 237 ############ 225 238 class Processors(gdb.Command): 226 """Cforall: Display currently known processors239 """Cforall: Display currently known processors 227 240 Usage: 228 info processors : print out all the processors in the Main Cluster 229 info processors <cluster_name> : print out all processors in a given cluster 241 info processors : print out all the processors in the Main Cluster 242 info processors all : print out all processors in all clusters 243 info processors <cluster_name> : print out all processors in a given cluster 230 244 """ 231 245 232 def __init__(self): 233 super(Processors, self).__init__('info processors', gdb.COMMAND_USER) 234 235 def print_processor(self, name, status, pending, address): 236 print('{:>20} {:>11} {:>13} {:>20}'.format(name, status, pending, address)) 237 238 def iterate_procs(self, root, active): 239 if root == 0x0: 240 return 241 242 cfa_t = get_cfa_types() 243 curr = root 244 245 while True: 246 processor = curr 247 should_stop = processor['_X12do_terminateVb_1'] 248 stop_count = processor['_X10terminatedS9semaphore_1']['_X5counti_1'] 249 if not should_stop: 250 status = 'Active' if active else 'Idle' 251 else: 252 status_str = 'Last Thread' if stop_count >= 0 else 'Terminating' 253 status = '{}({},{})'.format(status_str, should_stop, stop_count) 254 255 self.print_processor(processor['_X4namePKc_1'].string(), 256 status, str(processor['_X18pending_preemptionb_1']), str(processor) 257 ) 258 259 curr = curr['_X4nodeS28__processor____dbg_node_proc_1']['_X4nextPS9processor_1'] 260 261 if curr == root or curr == 0x0: 262 break 263 264 #entry point from gdb 265 def invoke(self, arg, from_tty): 266 if not is_cforall(): 267 return 268 269 cluster = lookup_cluster(arg if arg else None) 270 271 if not cluster: 272 print("No Cluster matching arguments found") 273 return 274 275 cfa_t = get_cfa_types() 276 print('Cluster: "{}"({})'.format(cluster['_X4namePKc_1'].string(), cluster.cast(cfa_t.cluster_ptr))) 277 278 active_root = cluster.cast(cfa_t.cluster_ptr) \ 279 ['_X5procsS8__dllist_S9processor__1'] \ 280 ['_X4headPY15__TYPE_generic__1'] \ 281 .cast(cfa_t.processor_ptr) 282 283 idle_root = cluster.cast(cfa_t.cluster_ptr) \ 284 ['_X5idlesS8__dllist_S9processor__1'] \ 285 ['_X4headPY15__TYPE_generic__1'] \ 286 .cast(cfa_t.processor_ptr) 287 288 if idle_root != 0x0 or active_root != 0x0: 289 self.print_processor('Name', 'Status', 'Pending Yield', 'Address') 290 self.iterate_procs(active_root, True) 291 self.iterate_procs(idle_root, False) 292 else: 293 print("No processors on cluster") 294 295 print() 246 def __init__(self): 247 super(Processors, self).__init__('info processors', gdb.COMMAND_USER) 248 249 def print_processor(self, name, status, pending, address): 250 print('{:>20} {:>11} {:>13} {:>20}'.format(name, status, pending, address)) 251 252 def iterate_procs(self, root, active): 253 if root == 0x0: 254 return 255 256 cfa_t = get_cfa_types() 257 curr = root 258 259 while True: 260 processor = curr 261 should_stop = processor['_X12do_terminateVb_1'] 262 stop_count = processor['_X10terminatedS9semaphore_1']['_X5counti_1'] 263 if not should_stop: 264 status = 'Active' if active else 'Idle' 265 else: 266 status_str = 'Last Thread' if stop_count >= 0 else 'Terminating' 267 status = '{}({},{})'.format(status_str, should_stop, stop_count) 268 269 self.print_processor(processor['_X4namePKc_1'].string(), 270 status, str(processor['_X18pending_preemptionb_1']), str(processor) 271 ) 272 273 curr = curr['_X4nodeS28__processor____dbg_node_proc_1']['_X4nextPS9processor_1'] 274 275 if curr == root or curr == 0x0: 276 break 277 278 #entry point from gdb 279 def invoke(self, arg, from_tty): 280 if not is_cforall(): 281 return 282 283 if not arg: 284 clusters = [lookup_cluster(None)] 285 elif arg == "all": 286 clusters = all_clusters() 287 else: 288 clusters = [lookup_cluster(arg)] 289 290 if not clusters: 291 print("No Cluster matching arguments found") 292 return 293 294 cfa_t = get_cfa_types() 295 for cluster in clusters: 296 print('Cluster: "{}"({})'.format(cluster['_X4namePKc_1'].string(), cluster.cast(cfa_t.cluster_ptr))) 297 298 active_root = cluster.cast(cfa_t.cluster_ptr) \ 299 ['_X5procsS8__dllist_S9processor__1'] \ 300 ['_X4headPY15__TYPE_generic__1'] \ 301 .cast(cfa_t.processor_ptr) 302 303 idle_root = cluster.cast(cfa_t.cluster_ptr) \ 304 ['_X5idlesS8__dllist_S9processor__1'] \ 305 ['_X4headPY15__TYPE_generic__1'] \ 306 .cast(cfa_t.processor_ptr) 307 308 if idle_root != 0x0 or active_root != 0x0: 309 self.print_processor('Name', 'Status', 'Pending Yield', 'Address') 310 self.iterate_procs(active_root, True) 311 self.iterate_procs(idle_root, False) 312 else: 313 print("No processors on cluster") 314 315 print() 296 316 297 317 ############ 298 318 class Threads(gdb.Command): 299 """Cforall: Display currently known threads319 """Cforall: Display currently known threads 300 320 Usage: 301 cfathreads : print Main Cluster threads, application threads only 302 cfathreads all : print all clusters, all threads 303 cfathreads <clusterName> : print cluster threads, application threads only 304 """ 305 def __init__(self): 306 # The first parameter of the line below is the name of the command. You 307 # can call it 'uc++ task' 308 super(Threads, self).__init__('info cfathreads', gdb.COMMAND_USER) 309 310 def print_formatted(self, marked, tid, name, state, address): 311 print('{:>1} {:>4} {:>20} {:>10} {:>20}'.format('*' if marked else ' ', tid, name, state, address)) 312 313 def print_thread(self, thread, tid, marked): 314 cfa_t = get_cfa_types() 315 self.print_formatted(marked, tid, thread['self_cor']['name'].string(), str(thread['state'].cast(cfa_t.thread_state)), str(thread)) 316 317 def print_formatted_cluster(self, str_format, cluster_name, cluster_addr): 318 print(str_format.format(cluster_name, cluster_addr)) 319 320 def print_threads_by_cluster(self, cluster, print_system = False): 321 # Iterate through a circular linked list of tasks and print out its 322 # name along with address associated to each cluster 323 threads = lookup_threads_by_cluster(cluster) 324 if not threads: 325 return 326 327 running_thread = find_curr_thread() 328 if running_thread is None: 329 print('Could not identify current thread') 330 331 self.print_formatted(False, '', 'Name', 'State', 'Address') 332 333 for t in threads: 334 if not t.is_system() or print_system: 335 self.print_thread(t.value, t.tid, t.value == running_thread if running_thread else False) 336 337 print() 338 339 def print_all_threads(self): 340 print("Not implemented") 341 342 def invoke(self, arg, from_tty): 343 """ 344 @arg: str 345 @from_tty: bool 346 """ 347 if not is_cforall(): 348 return 349 350 if not arg: 351 cluster = lookup_cluster() 352 if not cluster: 353 print("Could not find Main Cluster") 354 return 355 356 # only tasks and main 357 self.print_threads_by_cluster(cluster, False) 358 359 elif arg == 'all': 360 # all threads, all clusters 361 self.print_all_threads() 362 363 else: 364 cluster = lookup_cluster(arg) 365 if not cluster: 366 print("Could not find cluster '{}'".format(arg)) 367 return 368 369 # all tasks, specified cluster 370 self.print_threads_by_cluster(cluster, True) 321 cfathreads : print Main Cluster threads, application threads only 322 cfathreads all : print all clusters, all threads 323 cfathreads <clusterName> : print cluster threads, application threads only 324 """ 325 def __init__(self): 326 # The first parameter of the line below is the name of the command. You 327 # can call it 'uc++ task' 328 super(Threads, self).__init__('info cfathreads', gdb.COMMAND_USER) 329 330 def print_formatted(self, marked, tid, name, state, address): 331 print('{:>1} {:>4} {:>20} {:>10} {:>20}'.format('*' if marked else ' ', tid, name, state, address)) 332 333 def print_thread(self, thread, tid, marked): 334 cfa_t = get_cfa_types() 335 self.print_formatted(marked, tid, thread['self_cor']['name'].string(), str(thread['state'].cast(cfa_t.thread_state)), str(thread)) 336 337 def print_threads_by_cluster(self, cluster, print_system = False): 338 # Iterate through a circular linked list of tasks and print out its 339 # name along with address associated to each cluster 340 threads = lookup_threads_by_cluster(cluster) 341 if not threads: 342 return 343 344 running_thread = find_curr_thread() 345 if running_thread is None: 346 print('Could not identify current thread') 347 348 self.print_formatted(False, '', 'Name', 'State', 'Address') 349 350 for t in threads: 351 if not t.is_system() or print_system: 352 self.print_thread(t.value, t.tid, t.value == running_thread if running_thread else False) 353 354 print() 355 356 def print_all_threads(self): 357 for c in all_clusters(): 358 self.print_threads_by_cluster(c, False) 359 360 def invoke(self, arg, from_tty): 361 """ 362 @arg: str 363 @from_tty: bool 364 """ 365 if not is_cforall(): 366 return 367 368 if not arg: 369 cluster = lookup_cluster() 370 if not cluster: 371 print("Could not find Main Cluster") 372 return 373 374 # only tasks and main 375 self.print_threads_by_cluster(cluster, False) 376 377 elif arg == 'all': 378 # all threads, all clusters 379 self.print_all_threads() 380 381 else: 382 cluster = lookup_cluster(arg) 383 if not cluster: 384 print("Could not find cluster '{}'".format(arg)) 385 return 386 387 # all tasks, specified cluster 388 self.print_threads_by_cluster(cluster, True) 371 389 372 390 373 391 ############ 374 392 class Thread(gdb.Command): 375 def __init__(self): 376 # The first parameter of the line below is the name of the command. You 377 # can call it 'uc++ task' 378 super(Threads, self).__init__('cfathread', gdb.COMMAND_USER) 379 380 def print_usage(self): 381 print_usage(""" 382 cfathread : print userCluster tasks, application tasks only 383 cfathread <clusterName> : print cluster tasks, application tasks only 384 cfathread all : print all clusters, all tasks 385 cfathread <id> : switch stack to thread id on userCluster 386 cfathread 0x<address> : switch stack to thread on any cluster 387 cfathread <id> <clusterName> : switch stack to thread on specified cluster 388 """) 389 390 ############################ AUXILIARY FUNCTIONS ######################### 391 392 def print_formatted(self, marked, tid, name, state, address): 393 print('{:>1} {:>4} {:>20} {:>10} {:>20}'.format('*' if marked else ' ', tid, name, state, address)) 394 395 def print_thread(self, thread, tid, marked): 396 cfa_t = get_cfa_types() 397 self.print_formatted(marked, tid, thread['self_cor']['name'].string(), str(thread['state'].cast(cfa_t.thread_state)), str(thread)) 398 399 def print_formatted_cluster(self, str_format, cluster_name, cluster_addr): 400 print(str_format.format(cluster_name, cluster_addr)) 401 402 def print_tasks_by_cluster_all(self, cluster_address): 403 """ 404 Display a list of all info about all available tasks on a particular cluster 405 @cluster_address: gdb.Value 406 """ 407 cluster_address = cluster_address.cast(uCPPTypes.ucluster_ptr) 408 task_root = cluster_address['tasksOnCluster']['root'] 409 410 if task_root == 0x0 or task_root.address == 0x0: 411 print('There are no tasks for cluster at address: {}'.format(cluster_address)) 412 return 413 414 self.print_formatted_task('', 'Task Name', 'Address', 'State') 415 curr = task_root 416 task_id = 0 417 systask_id = -1 418 419 breakpoint_addr = self.find_curr_breakpoint_addr() 420 if breakpoint_addr is None: 421 return 422 423 while True: 424 global SysTask_Name 425 if (curr['task_']['name'].string() in SysTask_Name): 426 self.print_formatted_tasks(systask_id, breakpoint_addr, curr) 427 systask_id -= 1 428 else: 429 self.print_formatted_tasks(task_id, breakpoint_addr, curr) 430 task_id += 1 431 432 curr = curr['next'].cast(uCPPTypes.uBaseTaskDL_ptr_type) 433 if curr == task_root: 434 break 435 436 def print_tasks_by_cluster_address_all(self, cluster_address): 437 """ 438 Display a list of all info about all available tasks on a particular cluster 439 @cluster_address: str 440 """ 441 # Iterate through a circular linked list of tasks and print out its 442 # name along with address associated to each cluster 443 444 # convert hex string to hex number 445 try: 446 hex_addr = int(cluster_address, 16) 447 except: 448 self.print_usage() 449 return 450 451 cluster_address = gdb.Value(hex_addr) 452 if not self.print_tasks_by_cluster_all(cluster_address): 453 return 454 455 def print_threads_by_cluster(self, cluster, print_system = False): 456 """ 457 Display a list of limited info about all available threads on a particular cluster 458 @cluster: str 459 @print_system: bool 460 """ 461 # Iterate through a circular linked list of tasks and print out its 462 # name along with address associated to each cluster 463 464 threads = self.threads_by_cluster(cluster) 465 if not threads: 466 return 467 468 running_thread = self.find_curr_thread() 469 if running_thread is None: 470 print('Could not identify current thread') 471 472 self.print_formatted(False, '', 'Name', 'State', 'Address') 473 474 for t in threads: 475 if not t.is_system() or print_system: 476 self.print_thread(t.value, t.tid, t.value == running_thread if running_thread else False) 477 478 print() 479 480 ############################ COMMAND FUNCTIONS ######################### 481 482 def print_all_threads(self): 483 """Iterate through each cluster, iterate through all tasks and print out info about all the tasks 484 in those clusters""" 485 uCPPTypes = None 486 try: 487 uCPPTypes = get_uCPP_types() 488 except gdb.error: 489 print(not_supported_error_msg) 490 print(gdb.error) 491 return 492 493 cluster_root = get_cluster_root() 494 if cluster_root.address == 0x0: 495 return 496 497 curr = cluster_root 498 self.print_formatted_cluster(self.cluster_str_format, 'Cluster Name', 'Address') 499 500 while True: 501 addr = str(curr['cluster_'].reference_value())[1:] 502 self.print_formatted_cluster(self.cluster_str_format, curr['cluster_']['name'].string(), addr) 503 504 self.print_tasks_by_cluster_address_all(addr) 505 curr = curr['next'].cast(uCPPTypes.uClusterDL_ptr_type) 506 if curr == cluster_root: 507 break 508 509 def switchto(self, thread): 510 """Change to a new task by switching to a different stack and manually 511 adjusting sp, fp and pc 512 @task_address: str 513 2 supported format: 514 in hex format 515 <hex_address>: literal hexadecimal address 516 Ex: 0xffffff 517 in name of the pointer to the task 518 "task_name": pointer of the variable name of the cluster 519 Ex: T* s -> task_name = s 520 Return: gdb.value of the cluster's address 521 """ 522 # uCPPTypes = None 523 # try: 524 # uCPPTypes = get_uCPP_types() 525 # except gdb.error: 526 # print(not_supported_error_msg) 527 # print(gdb.error) 528 # return 529 530 # # Task address has a format "task_address", which implies that it is the 531 # # name of the variable, and it needs to be evaluated 532 # if task_address.startswith('"') and task_address.endswith('"'): 533 # task = gdb.parse_and_eval(task_address.replace('"', '')) 534 # else: 535 # # Task address format does not include the quotation marks, which implies 536 # # that it is a hex address 537 # # convert hex string to hex number 538 # try: 539 # hex_addr = int(task_address, 16) 540 # except: 541 # self.print_usage() 542 # return 543 # task_address = gdb.Value(hex_addr) 544 # task = task_address.cast(uCPPTypes.uBaseTask_ptr_type) 545 try: 546 if not gdb.lookup_symbol('__cfactx_switch'): 547 print('__cfactx_switch symbol is unavailable') 548 return 549 except: 550 print('here 3') 551 552 cfa_t = get_cfa_types() 553 554 state = thread['state'].cast(cfa_t.thread_state) 555 try: 556 if state == gdb.parse_and_eval('Halted'): 557 print('Cannot switch to a terminated thread') 558 return 559 560 if state == gdb.parse_and_eval('Start'): 561 print('Cannjot switch to a thread not yet run') 562 return 563 except: 564 print("here 2") 565 return 566 567 568 context = thread['context'] 569 570 # lookup for sp,fp and uSwitch 571 xsp = context['SP'] + 48 572 xfp = context['FP'] 573 574 # convert string so we can strip out the address 575 try: 576 xpc = get_addr(gdb.parse_and_eval('__cfactx_switch').address + 28) 577 except: 578 print("here") 579 return 580 581 # must be at frame 0 to set pc register 582 gdb.execute('select-frame 0') 583 584 # push sp, fp, pc into a global stack 585 global STACK 586 sp = gdb.parse_and_eval('$sp') 587 fp = gdb.parse_and_eval('$fp') 588 pc = gdb.parse_and_eval('$pc') 589 stack_info = StackInfo(sp = sp, fp = fp, pc = pc) 590 STACK.append(stack_info) 591 592 # update registers for new task 593 print('switching to ') 594 gdb.execute('set $rsp={}'.format(xsp)) 595 gdb.execute('set $rbp={}'.format(xfp)) 596 gdb.execute('set $pc={}'.format(xpc)) 597 598 def find_matching_gdb_thread_id(): 599 """ 600 Parse the str from info thread to get the number 601 """ 602 info_thread_str = gdb.execute('info thread', to_string=True).splitlines() 603 for thread_str in info_thread_str: 604 if thread_str.find('this={}'.format(task)) != -1: 605 thread_id_pattern = r'^\*?\s+(\d+)\s+Thread' 606 # retrive gdb thread id 607 return re.match(thread_id_pattern, thread_str).group(1) 608 609 # check if the task is running or not 610 if task_state == gdb.parse_and_eval('uBaseTask::Running'): 611 # find the equivalent thread from info thread 612 gdb_thread_id = find_matching_gdb_thread_id() 613 if gdb_thread_id is None: 614 print('cannot find the thread id to switch to') 615 return 616 # switch to that thread based using thread command 617 gdb.execute('thread {}'.format(gdb_thread_id)) 618 619 def switchto_id(self, tid, cluster): 620 """ 621 @cluster: cluster object 622 @tid: int 623 """ 624 threads = self.threads_by_cluster( cluster ) 625 626 for t in threads: 627 if t.tid == tid: 628 self.switchto(t.value) 629 return 630 631 print("Cound not find thread by id '{}'".format(tid)) 632 633 def invoke(self, arg, from_tty): 634 """ 635 @arg: str 636 @from_tty: bool 637 """ 638 if not is_cforall(): 639 return 640 641 argv = parse(arg) 642 print(argv) 643 if len(argv) == 0: 644 """ 645 Iterate only Main Thread, print only tasks and main 646 """ 647 cluster = lookup_cluster() 648 if not cluster: 649 print("Could not find Main Cluster") 650 return 651 652 # only tasks and main 653 self.print_threads_by_cluster(cluster, False) 654 655 elif len(argv) == 1: 656 if argv[0] == 'help': 657 self.print_usage() 658 # push task 659 elif argv[0].isdigit(): 660 cluster = lookup_cluster() 661 if not cluster: 662 print("Could not find Main Cluster") 663 return 664 665 try: 666 tid = int(argv[0]) 667 except: 668 print("'{}' not a valid thread id".format(argv[0])) 669 self.print_usage() 670 return 671 672 # by id, userCluster 673 self.switchto_id(tid, cluster) 674 675 elif argv[0].startswith('0x') or argv[0].startswith('0X'): 676 self.switchto(argv[0]) # by address, any cluster 677 # print tasks 678 elif argv[0] == 'all': 679 self.print_all_threads() # all tasks, all clusters 680 else: 681 """ 682 Print out all the tasks available in the specified cluster 683 @cluster_name: str 684 """ 685 print("cfathread by name") 686 cluster = lookup_cluster(argv[0]) 687 if not cluster: 688 return 689 690 # all tasks, specified cluster 691 self.print_threads_by_cluster(cluster, True) 692 693 elif len(argv) == 2: 694 # push task 695 self.pushtask_by_id(argv[0], argv[1]) # by id, specified cluster 696 else: 697 print('Invalid arguments') 698 self.print_usage() 393 """Cforall: Switch to specified user threads 394 Usage: 395 cfathread <id> : switch stack to thread id on main cluster 396 cfathread 0x<address> : switch stack to thread on any cluster 397 cfathread <id> <clusterName> : switch stack to thread on specified cluster 398 """ 399 def __init__(self): 400 # The first parameter of the line below is the name of the command. You 401 # can call it 'uc++ task' 402 super(Thread, self).__init__('cfathread', gdb.COMMAND_USER) 403 404 ############################ AUXILIARY FUNCTIONS ######################### 405 406 def switchto(self, thread): 407 """Change to a new task by switching to a different stack and manually 408 adjusting sp, fp and pc 409 @task_address: str 410 2 supported format: 411 in hex format 412 <hex_address>: literal hexadecimal address 413 Ex: 0xffffff 414 in name of the pointer to the task 415 "task_name": pointer of the variable name of the cluster 416 Ex: T* s -> task_name = s 417 Return: gdb.value of the cluster's address 418 """ 419 try: 420 if not gdb.lookup_symbol('__cfactx_switch'): 421 print('__cfactx_switch symbol is unavailable') 422 return 423 except: 424 print('here 3') 425 426 cfa_t = get_cfa_types() 427 428 state = thread['state'].cast(cfa_t.thread_state) 429 try: 430 if state == gdb.parse_and_eval('Halted'): 431 print('Cannot switch to a terminated thread') 432 return 433 434 if state == gdb.parse_and_eval('Start'): 435 print('Cannjot switch to a thread not yet run') 436 return 437 except: 438 print("here 2") 439 return 440 441 442 context = thread['context'] 443 444 # lookup for sp,fp and uSwitch 445 xsp = context['SP'] + 48 446 xfp = context['FP'] 447 448 # convert string so we can strip out the address 449 try: 450 xpc = get_addr(gdb.parse_and_eval('__cfactx_switch').address + 28) 451 except: 452 print("here") 453 return 454 455 # must be at frame 0 to set pc register 456 gdb.execute('select-frame 0') 457 458 # push sp, fp, pc into a global stack 459 global STACK 460 sp = gdb.parse_and_eval('$sp') 461 fp = gdb.parse_and_eval('$fp') 462 pc = gdb.parse_and_eval('$pc') 463 stack_info = StackInfo(sp = sp, fp = fp, pc = pc) 464 STACK.append(stack_info) 465 466 # update registers for new task 467 print('switching to ') 468 gdb.execute('set $rsp={}'.format(xsp)) 469 gdb.execute('set $rbp={}'.format(xfp)) 470 gdb.execute('set $pc={}'.format(xpc)) 471 472 def find_matching_gdb_thread_id(): 473 """ 474 Parse the str from info thread to get the number 475 """ 476 info_thread_str = gdb.execute('info thread', to_string=True).splitlines() 477 for thread_str in info_thread_str: 478 if thread_str.find('this={}'.format(task)) != -1: 479 thread_id_pattern = r'^\*?\s+(\d+)\s+Thread' 480 # retrive gdb thread id 481 return re.match(thread_id_pattern, thread_str).group(1) 482 483 # check if the task is running or not 484 if task_state == gdb.parse_and_eval('uBaseTask::Running'): 485 # find the equivalent thread from info thread 486 gdb_thread_id = find_matching_gdb_thread_id() 487 if gdb_thread_id is None: 488 print('cannot find the thread id to switch to') 489 return 490 # switch to that thread based using thread command 491 gdb.execute('thread {}'.format(gdb_thread_id)) 492 493 def switchto_id(self, tid, cluster): 494 """ 495 @cluster: cluster object 496 @tid: int 497 """ 498 threads = lookup_threads_by_cluster( cluster ) 499 500 for t in threads: 501 if t.tid == tid: 502 self.switchto(t.value) 503 return 504 505 print("Cound not find thread by id '{}'".format(tid)) 506 507 def invoke(self, arg, from_tty): 508 """ 509 @arg: str 510 @from_tty: bool 511 """ 512 if not is_cforall(): 513 return 514 515 argv = parse(arg) 516 print(argv) 517 if argv[0].isdigit(): 518 cname = " ".join(argv[1:]) if len(argv) > 1 else None 519 cluster = lookup_cluster(cname) 520 if not cluster: 521 print("Could not find cluster '{}'".format(cname if cname else "Main Cluster")) 522 return 523 524 try: 525 tid = int(argv[0]) 526 except: 527 print("'{}' not a valid thread id".format(argv[0])) 528 print_usage(self) 529 return 530 531 # by id, userCluster 532 self.switchto_id(tid, cluster) 533 534 elif argv[0].startswith('0x') or argv[0].startswith('0X'): 535 self.switchto(argv[0]) # by address, any cluster 699 536 700 537 ############ 701 538 class PrevThread(gdb.Command): 702 """Switch back to previous task on the stack"""703 usage_msg = 'prevtask'704 705 def __init__(self):706 super(PrevThread, self).__init__('prevtask', gdb.COMMAND_USER)707 708 def invoke(self, arg, from_tty):709 """710 @arg: str711 @from_tty: bool712 """713 global STACK714 if len(STACK) != 0:715 # must be at frame 0 to set pc register716 gdb.execute('select-frame 0')717 718 # pop stack719 stack_info = STACK.pop()720 pc = get_addr(stack_info.pc)721 sp = stack_info.sp722 fp = stack_info.fp723 724 # pop sp, fp, pc from global stack725 adjust_stack(pc, fp, sp)726 727 # must be at C++ frame to access C++ vars728 gdb.execute('frame 1')729 else:730 print('empty stack')539 """Switch back to previous task on the stack""" 540 usage_msg = 'prevtask' 541 542 def __init__(self): 543 super(PrevThread, self).__init__('prevtask', gdb.COMMAND_USER) 544 545 def invoke(self, arg, from_tty): 546 """ 547 @arg: str 548 @from_tty: bool 549 """ 550 global STACK 551 if len(STACK) != 0: 552 # must be at frame 0 to set pc register 553 gdb.execute('select-frame 0') 554 555 # pop stack 556 stack_info = STACK.pop() 557 pc = get_addr(stack_info.pc) 558 sp = stack_info.sp 559 fp = stack_info.fp 560 561 # pop sp, fp, pc from global stack 562 adjust_stack(pc, fp, sp) 563 564 # must be at C++ frame to access C++ vars 565 gdb.execute('frame 1') 566 else: 567 print('empty stack') 731 568 732 569 class ResetOriginFrame(gdb.Command): 733 """Reset to the origin frame prior to continue execution again"""734 usage_msg = 'resetOriginFrame'735 def __init__(self):736 super(ResetOriginFrame, self).__init__('reset', gdb.COMMAND_USER)737 738 def invoke(self, arg, from_tty):739 """740 @arg: str741 @from_tty: bool742 """743 global STACK744 if len(STACK) != 0:745 stack_info = STACK.pop(0)746 STACK.clear()747 pc = get_addr(stack_info.pc)748 sp = stack_info.sp749 fp = stack_info.fp750 751 # pop sp, fp, pc from global stack752 adjust_stack(pc, fp, sp)753 754 # must be at C++ frame to access C++ vars755 gdb.execute('frame 1')756 #else:757 #print('reset: empty stack') #probably does not have to print msg570 """Reset to the origin frame prior to continue execution again""" 571 usage_msg = 'resetOriginFrame' 572 def __init__(self): 573 super(ResetOriginFrame, self).__init__('reset', gdb.COMMAND_USER) 574 575 def invoke(self, arg, from_tty): 576 """ 577 @arg: str 578 @from_tty: bool 579 """ 580 global STACK 581 if len(STACK) != 0: 582 stack_info = STACK.pop(0) 583 STACK.clear() 584 pc = get_addr(stack_info.pc) 585 sp = stack_info.sp 586 fp = stack_info.fp 587 588 # pop sp, fp, pc from global stack 589 adjust_stack(pc, fp, sp) 590 591 # must be at C++ frame to access C++ vars 592 gdb.execute('frame 1') 593 #else: 594 #print('reset: empty stack') #probably does not have to print msg 758 595 759 596 Clusters() … … 762 599 PrevThread() 763 600 Threads() 601 Thread() 764 602 765 603 # Local Variables: #
Note:
See TracChangeset
for help on using the changeset viewer.