Changeset 9987d79
- Timestamp:
- May 1, 2020, 12:34:03 PM (5 years ago)
- Branches:
- ADT, arm-eh, ast-experimental, enum, forall-pointer-decay, jacob/cs343-translation, master, new-ast, new-ast-unique-expr, pthread-emulation, qualifiedEnum
- Children:
- 4069faad
- Parents:
- f6660520
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
tools/gdb/utils-gdb.py
rf6660520 r9987d79 26 26 27 27 class ThreadInfo: 28 29 30 31 32 33 34 35 36 37 28 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 53 return True 54 54 55 55 def get_cfa_types(): 56 57 58 59 60 61 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 66 67 68 69 70 71 72 73 74 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 77 print(obj.__doc__) 78 78 79 79 def parse(args): 80 81 82 83 84 85 86 87 88 89 90 91 92 80 """ 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 97 98 99 100 101 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_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 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 133 """ 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 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 166 # 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 198 return False 178 199 179 200 def adjust_stack(pc, fp, sp): 180 181 182 183 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 209 """Cforall: Display currently known clusters 189 210 Usage: 190 211 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 239 """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 319 """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 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 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 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 570 """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.