def varprint_start_no_create(self, rank, varobj, name, max_depth=gdbconf.varprint_max_depth, max_children=gdbconf.varprint_max_children, reset_maxes=False): """Start a varprint sequence where we have already created the variable object.""" v_id = self.varprint_id self.varprint_id += 1 self.varprint_stacks[v_id] = [(varobj, 0)] branch_depth = max_depth = VariableObjectManager.get_name_depth(name) def _list_handler(record): return self.varprint_dfs(record, rank, v_id, name, max_depth=max_depth, max_children=max_children, reset_maxes=reset_maxes, branch_depth=branch_depth, branch_name=name) tokens = self.run_gdb_command( Command("var-list-children", args=("1", '"' + varobj.name + '"')), rank) self.be.add_token_handler(tokens[rank], _list_handler)
def do_help(self, cmd, targets=None): """Run the help command.""" if not targets: # Because this makes the most sense, unless told otherwise, we run this on one processor. targets = 0 self.comm.send( GDBMessage(CMD_MSG, command=Command("interpreter-exec", args=("console", '"help ' + cmd + '"')), ranks=targets), targets)
def varprint_update(self, name, rank): """Check for updates on any of our variable objects.""" def _update_handler(record): if "changelist" not in record.results: print "Got a bad update record." return True for change in record.results["changelist"]: varobj = self.varobjs[rank].get_var_obj(change["name"]) if varobj: # Potentially, a variable object could be manually created that we're not tracking. if "in_scope" in change: if change["in_scope"] in ["false", "invalid"]: self.varobjs[rank].del_var_obj(varobj) del varobj # This probably isn't necessary. return False if "type_changed" in change and change[ "type_changed"] == "true": self.varobjs[rank].del_var_obj(varobj) del varobj return False if "value" in change: varobj.value = change["value"] if "dynamic" in change: varobj.is_dynamic = change["dynamic"] if "displayhint" in change: varobj.display_hint = change["displayhint"] if "num_new_children" in change: new_num = int(change["new_num_children"]) if new_num < len(varobj.children): # There has been a removal, so we no longer have child information. varobj.children = [] varobj.listed = False varobj.has_more = False else: if "new_children" in change: for child in change["new_children"]: varobj = VariableObjectManager.create_var_obj( child) if not varobj: print "Could not create child varobj!" return True if not self.varobjs[rank].add_var_obj( varobj): print "Could not add child varobj!" return True self.varprint_handler2(name, rank) tokens = self.run_gdb_command(Command("var-update", args=("1", "*")), rank) self.be.add_token_handler(tokens[rank], _update_handler)
def varprint_start(self, rank, name, max_depth=gdbconf.varprint_max_depth, max_children=gdbconf.varprint_max_children, reset_maxes=False): """Start a varprint command sequence by creating the varobj in GDB.""" v_id = self.varprint_id self.varprint_id += 1 base_name = VariableObjectManager.get_base_name(name) branch_depth = max_depth + VariableObjectManager.get_name_depth(name) def _list_handler(record): return self.varprint_dfs(record, rank, v_id, name, max_depth=max_depth, max_children=max_children, reset_maxes=False, branch_depth=branch_depth, branch_name=name) def _create_handler(record): varobj = VariableObjectManager.create_var_obj(record.results) if not varobj: # Bad variable name. return True if not self.varobjs[rank].add_var_obj(varobj): print "Could not add varobj." if int(varobj.num_child) > 0 or varobj.is_dynamic: # Set up our stack. self.varprint_stacks[v_id] = [(varobj, 0)] tokens = self.run_gdb_command( Command("var-list-children", args=("1", record.results["name"])), rank) self.be.add_token_handler(tokens[rank], _list_handler) else: self.comm.send( GDBMessage(VARPRINT_RES_MSG, varobj=varobj, rank=rank, err=False), self.comm.frontend) tokens = self.run_gdb_command( Command("var-create", args=(base_name, "*", base_name)), rank) self.be.add_token_handler(tokens[rank], _create_handler)
def _create_handler(record): varobj = VariableObjectManager.create_var_obj(record.results) if not varobj: # Bad variable name. return True if not self.varobjs[rank].add_var_obj(varobj): print "Could not add varobj." if int(varobj.num_child) > 0 or varobj.is_dynamic: # Set up our stack. self.varprint_stacks[v_id] = [(varobj, 0)] tokens = self.run_gdb_command( Command("var-list-children", args=("1", record.results["name"])), rank) self.be.add_token_handler(tokens[rank], _list_handler) else: self.comm.send( GDBMessage(VARPRINT_RES_MSG, varobj=varobj, rank=rank, err=False), self.comm.frontend)
def do_varassign(self, cmd, targets=None): """Run the varassign command.""" if not targets: targets = self.comm.get_mpiranks() split = cmd.split("=") if len(split) != 2: print "varassign format is: var = val" return var = split[0].strip() if var[0] == '"' and var[-1] == '"': var = var[1:-1] val = split[1].strip() for rank in targets.members(): full_name = self.varobjs[rank].get_full_name(var) if not full_name: print "Variable not found on rank {0}.".format(rank) continue self.comm.send( GDBMessage(CMD_MSG, command=Command("var-assign", args=('"' + full_name + '"', '"' + val + '"')), ranks=rank), rank)
def varprint_dfs(self, record, rank, v_id, name, max_depth=gdbconf.varprint_max_depth, max_children=gdbconf.varprint_max_children, reset_maxes=False, branch_depth=None, branch_name=None): """Do the depth-first search for expanding a variable object's children.""" cur_varobj, parent_depth = self.varprint_stacks[v_id].pop() cur_varobj.listed = True if "has_more" not in record.results: self.comm.send( GDBMessage(VARPRINT_RES_MSG, rank=rank, err=True, msg="Got bad variable data."), self.comm.frontend) elif "children" in record.results: if len(record.results["children"]) > max_children: cur_varobj.more_children = True for child_tup in record.results["children"][:max_children]: child = child_tup[1] varobj = VariableObjectManager.create_var_obj(child) if not varobj: print "Could not create child varobj!" return True if not self.varobjs[rank].add_var_obj(varobj): print "Could not add child varobj!" return True if int(varobj.num_child) > 0 or varobj.is_dynamic: # Only potentially push if the varobj can have children. do_listing = True if parent_depth > max_depth: # If the depth of the parent of this node is greater than five, # we want to terminate the search of this branch, unless this # node is a pseduo-child, or we want to go deeper on one branch. if branch_name and VariableObjectManager.same_branch( varobj.name, branch_name): if parent_depth > branch_depth and not VariableObjectManager.is_pseudochild( varobj): do_listing = False elif not VariableObjectManager.is_pseudochild(varobj): do_listing = False # Don't list null-pointers. if varobj.vartype and varobj.value and varobj.vartype[ -1] == "*": try: if int(varobj.value, 0) == 0: do_listing = False except ValueError: pass # Do not evaluate children further when there's an excessive number. if len(record.results["children"]) > 128: do_listing = False # Add to the stack to list if we meet the requirements. if do_listing: self.varprint_stacks[v_id].append( (varobj, parent_depth + 1)) if not self.varprint_stacks[v_id]: to_send = self.varobjs[rank].get_var_obj(name) if to_send: self.comm.send( GDBMessage(VARPRINT_RES_MSG, varobj=to_send, rank=rank, err=False), self.comm.frontend) else: self.comm.send( GDBMessage(VARPRINT_RES_MSG, rank=rank, err=True, msg="Variable does not exist."), self.comm.frontend) else: to_list, depth = self.varprint_stacks[v_id][-1] if reset_maxes: def _list_handler(record): return self.varprint_dfs(record, rank, v_id, name, branch_depth=branch_depth, branch_name=branch_name) else: def _list_handler(record): return self.varprint_dfs(record, rank, v_id, name, max_depth=max_depth, max_children=max_children, reset_maxes=reset_maxes, branch_depth=branch_depth, branch_name=branch_name) tokens = self.run_gdb_command( Command("var-list-children", args=("1", '"' + to_list.name + '"')), rank) self.be.add_token_handler(tokens[rank], _list_handler)
def init_gdb(self): """Initialize GDB-related things, and launch the GDB process.""" # Indexed by MPI rank. self.varobjs = {} # Maps tokens to MPI rank. self.token_rank_map = {} self.record_handler = GDBMIRecordHandler() self.record_handler.add_type_handler( self._watch_thread_created, set([mi.gdbmi_records.ASYNC_NOTIFY_THREAD_CREATED])) self.startup_stop_hid = self.record_handler.add_type_handler( self._watch_startup_stop, set([mi.gdbmi_records.ASYNC_EXEC_STOPPED])) gdb_env = {} if gdbconf.use_sbd: self.sbd = SBDBE(self.comm) gdb_env["LD_PRELOAD"] = gdbconf.sbd_bin else: self.sbd = None enable_pprint_cmd = Command("enable-pretty-printing") enable_target_async_cmd = Command("gdb-set", args=["target-async", "on"]) disable_pagination_cmd = Command("gdb-set", args=["pagination", "off"]) enable_non_stop_cmd = Command("gdb-set", args=["non-stop", "on"]) add_inferior_cmd = Command("add-inferior") self.gdb = GDBMachineInterface(gdb=gdbconf.gdb_path, gdb_args=["-x", gdbconf.gdb_init_path], env=gdb_env) procs = self.comm.get_proctab() # Set up GDB. if not self.run_gdb_command(enable_pprint_cmd): raise RuntimeError("Could not enable pretty printing!") if not self.run_gdb_command(enable_target_async_cmd): raise RuntimeError("Could not enable target-async!") if not self.run_gdb_command(disable_pagination_cmd): raise RuntimeError("Could not disable pagination!") if not self.run_gdb_command(enable_non_stop_cmd): raise RuntimeError("Could not enable non-stop!") # Create inferiors and set up MPI rank/inferior map. # First inferior is created by default. self.rank_inferior_map = {procs[0].mpirank: 'i1'} self.inferior_rank_map = {'i1': procs[0].mpirank} i = 2 for proc in procs[1:]: # Hackish: Assume that the inferiors follow the iN naming scheme. self.rank_inferior_map[proc.mpirank] = 'i' + str(i) self.inferior_rank_map['i' + str(i)] = proc.mpirank i += 1 if not self.run_gdb_command(add_inferior_cmd, no_thread=True): raise RuntimeError('Cound not add inferior i{0}!'.format(i - 1)) # Maps MPI ranks to associated threads and vice-versa. self.rank_thread_map = {} self.thread_rank_map = {} if self.sbd: # Set up the list of executables for load file checking. self.sbd.set_executable_names( [os.path.basename(proc.pd.executable_name) for proc in procs]) # Attach processes. for proc in procs: if not self.run_gdb_command(Command( "target-attach", opts={ '--thread-group': self.rank_inferior_map[proc.mpirank] }, args=[proc.pd.pid]), proc.mpirank, no_thread=True): raise RuntimeError("Could not attach to rank {0}!".format( proc.mpirank)) self.varobjs[proc.mpirank] = VariableObjectManager() # Cludge to fix GDB not outputting records for the i1 attach. if self.rank_inferior_map[proc.mpirank] == 'i1': time.sleep(0.1)
def do_quit(self, cmd, targets=None): """Gracefully quit PGDB.""" self.quit = True self.comm.send(GDBMessage(CMD_MSG, command=Command("gdb-exit")), self.comm.broadcast)