Ejemplo n.º 1
0
// Find path of source file SOURCE
string dbx_path(const string& source)
{
    string path;
    if (gdb->has_setenv_command() && gdb->has_edit_command())
    {
	// The DBX `file' command issues only the base name of the
	// current file.  The `edit' command, however, invokes an
	// editor with the entire path.  So, we misuse the `edit'
	// command such that it reports the entire path.
	gdb_question("setenv EDITOR \"echo\"");
	path = gdb_question("edit " + source);
	gdb_question(string("setenv EDITOR ") + 
		     quote(getenv("EDITOR") ? getenv("EDITOR") : "vi"));
    }
    else if (gdb->type() == DBX)
    {
	// We have DBX, but no `setenv' and no `edit' command.  Check
	// whether the `file' command with no arguments provides the
	// full path, as in AIX DBX 3.1.  This shouldn't affect other
	// DBX variants as `file' will simply return the same thing
	// already contained in source.
	gdb_question("file " + source);
	path = gdb_question("file");
    }

    strip_leading_space(path);
    if (!path.contains('/', 0) || path.contains(' '))
	path = source;		// Sanity check

    strip_trailing_space(path);
    return path;
}
Ejemplo n.º 2
0
// Return 1 if the signal specified in PROGRAM_STATE is passed to the
// program; 0 if not, -1 if undecided.
static int passed_to_program(const string& program_state)
{
    string signal = program_state.from("SIG");
    signal = signal.through(rxalpha);

    if (!signal.empty())
    {
	string signal_description = program_state.after(signal);
	signal_description = signal_description.after(rxwhite);

	if (signal_description.empty())
	    signal_description = signal;
	
	defineConversionMacro("SIGNAL", signal.chars());
	defineConversionMacro("SIGNAL_DESCRIPTION", signal_description.chars());

	string ans = gdb_question("info handle " + signal);

	// `info handle SIGINT' output has the form
	// "Signal        Stop\tPrint\tPass to program\tDescription\n"
	// "SIGINT        Yes\tYes\tNo\t\tInterrupt\n"

	ans.downcase();
	string header = ans.before("pass ");
	int tabs_before_pass = header.freq('\t');
	string info = ans.after('\n');
	while (tabs_before_pass--)
	    info = info.after('\t');
	if (info.contains('y', 0))
	    return 1;
	if (info.contains('n', 0))
	    return 0;
    }
    return -1;
}
Ejemplo n.º 3
0
static void LoadSharedLibrariesCB(Widget, XtPointer, XtPointer)
{
    StatusDelay delay("Loading shared object library symbols");
    
    gdb_question("sharedlibrary");
    update_sources();
}
Ejemplo n.º 4
0
// Get list of sources into SOURCES_LIST
void get_gdb_sources(StringArray& sources_list)
{
    static const StringArray empty;
    sources_list = empty;

    string ans = gdb_question("info sources");
    if (ans != NO_GDB_ANSWER)
    {
	// Create a newline-separated list of sources
	string new_ans;
	while (!ans.empty())
	{
	    string line = ans.before('\n');
	    ans = ans.after('\n');

	    if (line.empty() || line.contains(':', -1))
		continue;

	    line.gsub(", ", "\n");
	    new_ans += line + '\n';
	}

	ans = new_ans;
	while (!ans.empty())
	{
	    string line = ans.before('\n');
	    ans = ans.after('\n');
	    
	    sources_list += line;
	}

	smart_sort(sources_list);
	uniq(sources_list);
    }
}
Ejemplo n.º 5
0
// Get index base of expr EXPR in dimension DIM
int DispValue::index_base(const string& expr, int dim)
{
    if (gdb->program_language() != LANGUAGE_FORTRAN)
	return gdb->default_index_base();

    string base = expr;
    if (base.contains('('))
	base = base.before('(');
    if (!type_cache.has(base))
	type_cache[base] = gdb_question(gdb->whatis_command(base));
    string type = type_cache[base];

    // GDB issues array information as `type = real*8 (0:9,2:12)'.
    // However, the first dimension in the type output comes last in
    // the printed array.
    int colon = type.length();
    while (colon >= 0 && dim-- >= 0)
	colon = type.index(':', colon - type.length() - 1);
    if (colon < 0)
	return  gdb->default_index_base(); // Not found

    while (colon >= 0 && isdigit(type[colon - 1]))
	colon--;

    return atoi(type.chars() + colon);
}
Ejemplo n.º 6
0
// Get information on current debuggee
ProgramInfo::ProgramInfo()
    : file(NO_GDB_ANSWER),
      core(NO_GDB_ANSWER),
      pid(0),
      attached(false),
      running(false),
      state()
{
    if (source_view->have_exec_pos())
    {
	state = "has stopped";
	running = true;
    }
    else
    {
	state = "is not being run";
	running = false;
    }

    switch(gdb->type())
    {
    case GDB:
    case PYDB:
    case DBG:
    {
    	string ans;

    	if (gdb->is_windriver_gdb())
	{
	    // Windriver GDB (VxWorks).

	    // VxWorks allows multiple dynamically relocatable
	    // programs to be loaded simultaneously. Before a program
	    // is run, the 'info source' command can report
	    // information from a source file not related to the
	    // program just downloaded for debugging. (The WindRiver
	    // version of gdb does not support the 'info files'
	    // command.)

	    // In order to tell DDD that there is indeed a source file
	    // available, we need to first see if a program has
	    // already been started. If so, then the 'info source'
	    // command can be used.

	    // Otherwise, the 'info sources' command is used, and the
	    // first file in the list is used, assuming it is related
	    // to the current program that was downloaded.

	    // See if the program has been run first
	    ans = gdb_question("info frame");
	    if (ans == NO_GDB_ANSWER)
		break;

	    file = "";
	    if (ans.contains("No stack"))
	    {
		// Then try using info sources and use first file listed
		ans = gdb_question("info sources");
		if (ans == NO_GDB_ANSWER)
		    break;

		if (ans.contains("Source files for which "
				 "symbols have been read in:"))
		{
		    file = ans.after("\n");
		    file = file.before(" ");
		    file = unquote(file);
		}
	    }
	    else
	    {
	    	// Try using `info source'.
		ans = gdb_question("info source");
		if (ans == NO_GDB_ANSWER)
		    break;

		if (ans.contains("Current source file is "))
		{
		    file = ans.after("Current source file is ");
		    file = file.before(".\n");
		    file = unquote(file);
		}
	    }
	}
	else
	{
	    // Ordinary GDB.
	    ans = gdb_question("info files");
	    if (ans == NO_GDB_ANSWER)
		break;

	    file = "";
	    if (ans.contains("Symbols from "))
	    {
		file = ans.after("Symbols from ");
		file = file.before(".\n");
		file = unquote(file);
	    }

	}
	core = "";
	if (ans.contains("core dump"))
	{
	    core = ans.after("core dump");
	    core = core.after('`');
	    core = core.before("',");
	}

	if (ans.contains("process "))
	{
	    string p = ans.after("process ");
	    pid = atoi(p.chars());
	}

	attached = ans.contains("attached process ");

	ans = gdb_question("info program");
	if (ans == NO_GDB_ANSWER)
	    break;

	if (ans.contains("not being run"))
	    running = false;
	else if (ans.contains("\nIt stopped "))
	{
	    state = ans.from("\nIt stopped ");
	    state = "has " + state.after("\nIt ");
	    state = state.before('.');
	    running = true;
	}
	break;
    }

    case DBX:
    {
	if (gdb->is_ladebug())
	{
	    string ans = gdb_question("show process");
	    // typical answers:
	    // 1:no process 
	    // There are no processes being debugged.
	    // 2: process has been paused.
	    // Current Process: localhost:26177 (a.out) paused.
	    // 3: process terminated
	    // Current Process: localhost:13614 (ddd) terminated.
	    // TODO: treat the terminated case 
     
	    if (ans != NO_GDB_ANSWER && 
		!ans.contains("no processes being debugged"))
	    {
		if (ans.contains("Current Process: "))
		{
		    ans = ans.after(": ");
		    {
			string p = ans.after(":");
			p = p.before(" ");
			pid = atoi(p.chars());
		    }
		    ans = ans.after(" (");
		    file = ans.before(")");

		    ans = ans.after(") ");
		    running = ans.contains("paused");
		    // ladebug always creates a process.
		    // It may be "loaded" or attached.
		    attached = true;
		}
	    }	    
	}

	// AD TODO: shouldn't it be an "else" ?

	string ans = gdb_question(gdb->debug_command());
	if (ans != NO_GDB_ANSWER)
	{
	    if (ans.contains("Current givenfile is ", 0))
		ans = ans.after("Current givenfile is ");
	    else if (ans.contains("Debugging: ", 0))
		ans = ans.after(": ");

	    strip_space(ans);
	    if (!ans.contains(' ')) // Sanity check
		file = ans;
	}
	break;
    }

    case XDB:
	break;			// FIXME

    case PERL:
	// Use the program we were invoked with
	file = gdb->program();
	if (file.matches(rxint))
	    file = "";		// Invoked with a constant expression

	if (file.empty())
	{
	    // Not invoked with a program?  Use the current file, then.
	    file = source_view->file_of_cursor();
	    file = file.before(":");
	}
	core = "";
	break;

    case BASH:
	// Use the program we were invoked with
	file = gdb->program();
	if (file.matches(rxint))
	    file = "";		// Invoked with a constant expression

	if (file.empty())
	{
	    // Not invoked with a program?  Use the current file, then.
	    file = source_view->file_of_cursor();
	    file = file.before(":");
	}
	core = "";
	break;

    case JDB:
	// Just use the current class.
	file = source_view->line_of_cursor();
	file = file.before(":");
	core = "";

	// Save whether JDB's VM is running
	static int last_jdb_pid = -1;
	static bool jvm_running = false;

	if (gdb->pid() != last_jdb_pid)
	{
	    // New JDB: reset info
	    jvm_running = false;
	    last_jdb_pid = gdb->pid();
	}

	// The VM is running iff the prompt contains a backtrace
	// level ("[n]").
	if (!jvm_running && gdb->prompt().contains("["))
	    jvm_running = true;

	running = jvm_running;
	break;
    }

    if (file == NO_GDB_ANSWER)
    {
	// As a fallback, get core file and executable from argument list.
	// Works only on local file system and is more a guess.
	char **argv = saved_argv();
	int argc = 0;
	while (argv[argc] != 0)
	    argc++;

	for (int i = argc - 1; i > 0 && file == NO_GDB_ANSWER; i--)
	{
	    // All debuggers supported by DDD have [EXEC [CORE]] as
	    // their last arguments.
	    string arg = argv[i];
	    if (is_core_file(arg))
		core = arg;
	    else if (is_debuggee_file(arg))
		file = arg;
	}
    }

    if (file != NO_GDB_ANSWER)
	add_to_recent(file);
}
Ejemplo n.º 7
0
// Create list of processes
static void update_processes(Widget processes, bool keep_selection)
{
    StatusDelay delay("Getting list of processes");

    string cmd = sh_command(app_data.ps_command) + " 2>&1";
    FILE *fp = popen(cmd.chars(), "r");
    if (fp == 0)
    {
	delay.outcome = strerror(errno);
	return;
    }

    StringArray all_process_list;
    int c;
    string line = "";
    bool first_line = true;

    while ((c = getc(fp)) != EOF)
    {
	if (c == '\n')
	{
	    if (first_line || valid_ps_line(line, app_data.ps_command))
		all_process_list += line;
#if 0
	    else
		std::clog << "Excluded: " << line << "\n";
#endif

	    if (first_line)
	    {
		// Find first occurrence of `PID' title
		ps_pid_index = line.index(" PID ");
		if (ps_pid_index < 0)
		    ps_pid_index = 0;
	    }

	    line = "";
	    first_line = false;
	}
	else
	{
	    line += c;
	}
    }

    pclose(fp);
    sortProcesses(all_process_list);
    DynIntArray pids(all_process_list.size());

    // If GDB cannot send a signal to the process, we cannot debug it.
    // Try a `kill -0' (via GDB, as it may be setuid) and filter out
    // all processes in the `kill' diagnostic -- that is, all
    // processes that `kill' could not send a signal.
    string kill = "kill -0";

    if (gdb->has_handler_command())
	kill = "/usr/bin/kill -0"; // Bypass built-in SUN DBX command

    int i;
    for (i = 0; i < all_process_list.size(); i++)
    {
	pids[i] = ps_pid(all_process_list[i]);
	if (pids[i])
	    kill += string(" ") + itostring(pids[i]);
    }
#if defined(__sun) 
    // bypass underlying debugger
    // Fix for Sun: use /usr/bin/kill
    string kill_result;
    {
      std::ostringstream os;
      kill += " 2>&1";
      FILE *fp = popen(kill.chars(), "r");
      if (fp != 0)
      {
	  int c;
	  while ((c = getc(fp)) != EOF)
	  {
	      os << (char)c;
	  }
	  pclose(fp);
      }
      kill_result = os;
    }
#else
    string kill_result = gdb_question(gdb->shell_command(kill));
#endif
    i = 0;
    while (i >= 0)
    {
	i = kill_result.index(rxint, i);
	if (i >= 0)
	{
	    int bad_pid = atoi(kill_result.chars() + i);
	    for (int k = 0; k < all_process_list.size(); k++)
	    {
		if (pids[k] != 0 && pids[k] == bad_pid)
		{
#if 0
		    std::clog << "Excluded: " << all_process_list[k] << "\n";
#endif
		    all_process_list[k] = NO_GDB_ANSWER;
		}
	    }
	    i++;
	}
    }

    StringArray process_list;
    for (i = 0; i < all_process_list.size(); i++)
	if (all_process_list[i] != NO_GDB_ANSWER)
	    process_list += all_process_list[i];

    // Now set the selection.
    bool *selected = new bool[process_list.size()];
    for (i = 0; i < process_list.size(); i++)
	selected[i] = false;

    int pos = -1;
    if (keep_selection)
    {
	// Preserve old selection: each PID selected before will also be
	// selected after.
	IntArray selection;
	getPIDs(processes, selection);

	for (i = 0; i < selection.size(); i++)
	{
	    for (int j = 0; j < process_list.size(); j++)
		if (selection[i] == ps_pid(process_list[j]))
		{
		    if (pos < 0)
			pos = j;
		    selected[j] = true;
		}
	}
    }

    if (pos < 0)
    {
	// Create new selection from current file and current pid.
	ProgramInfo info;

	// Check for current pid; if found, highlight it.
	for (i = 0; pos < 0 && i < process_list.size(); i++)
	{
	    if (info.pid != 0 && ps_pid(process_list[i]) == info.pid)
		pos = i;
	}

	if (pos < 0)
	{
	    // Not found? Try leftmost occurrence of process base name.
	    string current_base = basename(info.file.chars());
	    int leftmost = INT_MAX;
	    for (i = 0; i < process_list.size(); i++)
	    {
		int occurrence = process_list[i].index(current_base);
		if (occurrence >= 0 && occurrence < leftmost 
		    && ps_pid(process_list[i]) > 0)
		{
		    leftmost = occurrence;
		    pos = i;
		}
	    }
	}
    }

    if (pos >= 0)
	selected[pos] = true;

    setLabelList(processes, process_list.values(),
		 selected, process_list.size(), true, false);

    if (pos >= 0)
	ListSetAndSelectPos(processes, pos + 1);

    delete[] selected;
}
Ejemplo n.º 8
0
string dbx_lookup(const string& func_name, bool silent)
{
    // Protect against `1' or `' being looked up as function names
    if (!func_name.contains(rxidentifier, 0))
	return "";		// Bad function name

    if (pos_cache.has(func_name))
    {
	string pos = pos_cache[func_name];
	if (silent || !pos.empty())
	    return pos;
    }

    string reply;
    switch (gdb->type())
    {
    case DBG:
    case DBX:
    case GDB:
    case JDB:
    case PYDB:
	reply = gdb_question("list " + func_name, 0, true);
	break;

    case XDB:
	reply = gdb_question("v " + func_name, 0, true);
	break;

    case PERL:
	reply = gdb_question("l " + func_name, 0, true);
	break;

    case BASH:
	reply = gdb_question("l " + func_name, 0, true);
	break;

    case MAKE:
	reply = gdb_question("target " + func_name, 0, true);
	break;
    }

    if (reply == NO_GDB_ANSWER)
    {
	// post_gdb_busy();
	return "";
    }

    string file = "";
    int line    = 0;
    switch (gdb->type())
    {
    case GDB:
    case PYDB:	// XXX
    {
	file = reply.from('\"');
	file = file.before('\"');
	const string line_s = reply.after("Line ");
	line = atoi(line_s.chars());
	break;
    }

    case DBX:
	line = line_of_listing(reply, silent);
	if (line > 0)
	{
	    file = gdb_question("file");
	    strip_trailing_space(file);
	}
	break;

    case BASH:
    case DBG:
    case JDB:
    case MAKE:
    case PERL:
	line = line_of_listing(reply, silent);
	file = source_view->line_of_cursor();
	file = file.before(':');
	break;

    case XDB:
    {
#if RUNTIME_REGEX
	static regex rxcolons("[^:]*:[^:]*: *[0-9][0-9]*.*");
#endif
	if (reply.matches(rxcolons))
	{
	    file = reply.before(':');
	    reply = reply.after(':'); // Skip file
	    reply = reply.after(':'); // Skip function
	    strip_leading_space(reply);
	    const string line_s = reply.before(':');
	    line = atoi(line_s.chars());
	}
	else
	{
	    // post_gdb_message(reply);
	    return "";
	}
	break;
    }
    }

    string pos = "";
    if (line > 0)
	pos = file + ":" + itostring(line);

    pos_cache[func_name] = pos;
    return pos;
}
Ejemplo n.º 9
0
bool UndoBuffer::process_command(UndoBufferEntry& entry)
{
    // Process command
    string commands;
    if (entry.has(UB_EXEC_COMMAND))
	commands = entry[UB_EXEC_COMMAND];
    else if (entry.has(UB_COMMAND))
	commands = entry[UB_COMMAND];
    else
	return true;		// Nothing to do

    entry.remove(UB_COMMAND);
    entry.remove(UB_EXEC_COMMAND);

    //string original_commands = commands;
    int bp_count = 0;
    undoing = true;

    bool confirm = false;

    if (!commands.empty() && gdb->type() == GDB)
    {
	gdb_command("show confirm", 0, get_confirm, &confirm);
	syncCommandQueue();
    }

    if (confirm)
    {
	// Turn confirmation off during undo/redo.
	gdb_question("set confirm off");
    }

    while (!commands.empty())
    {
	string cmd;
	if (commands.contains('\n'))
	    cmd = commands.before('\n');
	else
	    cmd = commands;
	commands = commands.after('\n');

	// Handle breakpoint remappings
	if (cmd.contains(REMAP_COMMAND, 0))
	{
	    int old_bp_nr = atoi(cmd.chars() + strlen(REMAP_COMMAND "@"));
	    int new_bp_nr = source_view->next_breakpoint_number() + bp_count++;

	    remap_breakpoint(old_bp_nr, new_bp_nr);
	    remap_breakpoint(commands, old_bp_nr, new_bp_nr);

	    continue;
	}

	// Replace all occurrences of `@N@' by N
#if RUNTIME_REGEX
	static regex rxnum("@[0-9]+@");
#endif
	int i;
	while ((i = index(cmd, rxnum, "@")) >= 0)
	{
	    int num = atoi(cmd.chars() + i + 1);
	    int j = cmd.index('@', i + 1);
	    cmd.at(i, j - i + 1) = itostring(num);
	}

	if (cmd.contains("set confirm", 0))
	    confirm = false;	// Don't overwrite

	// Execute command.  This will result in new redo command(s)
	// being passed to add_command().
	Command c(cmd);
	c.priority = COMMAND_PRIORITY_SYSTEM;
	gdb_command(c);

	// Wait until this command is processed
	syncCommandQueue();
    }

    if (confirm)
	gdb_question("set confirm on");

    if (!entry.has(UB_COMMAND) && !entry.has(UB_EXEC_COMMAND))
    {
	// We had an error during execution
	return false;
    }

    undoing = false;

    return true;
}