58c03c
commit 0f65ae0c36bf04e22219f28c32c3ae0cdee5acfe
58c03c
Author: Dave Anderson <anderson@redhat.com>
58c03c
Date:   Fri Dec 7 15:17:37 2018 -0500
58c03c
58c03c
    Implemented a new plugin function for the readline library's tab
58c03c
    completion feature.  Without the patch, the use of the default plugin
58c03c
    from the embedded gdb module has been seen to cause segmentation
58c03c
    violations or other fatal malloc/free/corruption assertions.  The new
58c03c
    plugin takes gdb out of the picture entirely, and also restricts the
58c03c
    matching options to just symbol names, so as not to clutter the
58c03c
    results with irrelevant filenames.
58c03c
    (anderson@redhat.com)
58c03c
58c03c
diff --git a/cmdline.c b/cmdline.c
58c03c
index cf3e150..665f48c 100644
58c03c
--- a/cmdline.c
58c03c
+++ b/cmdline.c
58c03c
@@ -40,6 +40,8 @@ int shell_command(char *);
58c03c
 static void modify_orig_line(char *, struct args_input_file *);
58c03c
 static void modify_expression_arg(char *, char **, struct args_input_file *);
58c03c
 static int verify_args_input_file(char *);
58c03c
+static char *crash_readline_completion_generator(const char *, int);
58c03c
+static char **crash_readline_completer(const char *, int, int);
58c03c
 
58c03c
 #define READLINE_LIBRARY
58c03c
 
58c03c
@@ -2071,6 +2073,9 @@ readline_init(void)
58c03c
 	if (STREQ(pc->editing_mode, "emacs")) {
58c03c
         	rl_editing_mode = emacs_mode;
58c03c
 	}
58c03c
+
58c03c
+	rl_attempted_completion_function = crash_readline_completer;
58c03c
+	rl_attempted_completion_over = 1;
58c03c
 }
58c03c
 
58c03c
 /*
58c03c
@@ -2605,3 +2610,27 @@ exec_args_input_file(struct command_table_entry *ct, struct args_input_file *aif
58c03c
 	fclose(pc->args_ifile);
58c03c
 	pc->args_ifile = NULL;
58c03c
 }
58c03c
+
58c03c
+static char *
58c03c
+crash_readline_completion_generator(const char *match, int state)
58c03c
+{
58c03c
+	static struct syment *sp_match;
58c03c
+
58c03c
+	if (state == 0)
58c03c
+		sp_match = NULL;
58c03c
+
58c03c
+	sp_match = symbol_complete_match(match, sp_match);
58c03c
+
58c03c
+	if (sp_match)
58c03c
+		return(strdup(sp_match->name));
58c03c
+	else
58c03c
+		return NULL;
58c03c
+}
58c03c
+
58c03c
+static char **
58c03c
+crash_readline_completer(const char *match, int start, int end)
58c03c
+{
58c03c
+	rl_attempted_completion_over = 1;
58c03c
+	return rl_completion_matches(match, crash_readline_completion_generator);
58c03c
+}
58c03c
+
58c03c
diff --git a/defs.h b/defs.h
58c03c
index 9ce32c1..a3cb5a4 100644
58c03c
--- a/defs.h
58c03c
+++ b/defs.h
58c03c
@@ -5138,6 +5138,7 @@ void parse_for_member_extended(struct datatype_member *, ulong);
58c03c
 void add_to_downsized(char *);
58c03c
 int is_downsized(char *);
58c03c
 int is_string(char *, char *);
58c03c
+struct syment *symbol_complete_match(const char *, struct syment *);
58c03c
 
58c03c
 /*  
58c03c
  *  memory.c 
58c03c
diff --git a/symbols.c b/symbols.c
58c03c
index 05628ff..0769294 100644
58c03c
--- a/symbols.c
58c03c
+++ b/symbols.c
58c03c
@@ -13071,3 +13071,73 @@ is_downsized(char *name)
58c03c
 
58c03c
 	return FALSE;
58c03c
 }
58c03c
+
58c03c
+struct syment *
58c03c
+symbol_complete_match(const char *match, struct syment *sp_last)
58c03c
+{
58c03c
+	int i;
58c03c
+	struct syment *sp, *sp_end, *sp_start;
58c03c
+	struct load_module *lm;
58c03c
+	int search_init;
58c03c
+
58c03c
+	if (sp_last) {
58c03c
+		sp_start = next_symbol(NULL, sp_last);
58c03c
+		if (!sp_start)
58c03c
+			return NULL;
58c03c
+	} else	
58c03c
+		sp_start = st->symtable;
58c03c
+
58c03c
+	if ((sp_start >= st->symtable) && (sp_start < st->symend)) {
58c03c
+		for (sp = sp_start; sp < st->symend; sp++) {
58c03c
+			if (STRNEQ(sp->name, match))
58c03c
+				return sp;
58c03c
+		}
58c03c
+		sp_start = NULL;
58c03c
+	}
58c03c
+
58c03c
+	search_init = FALSE;
58c03c
+
58c03c
+	for (i = 0; i < st->mods_installed; i++) {
58c03c
+		lm = &st->load_modules[i];
58c03c
+		if (lm->mod_flags & MOD_INIT)
58c03c
+			search_init = TRUE;
58c03c
+		sp_end = lm->mod_symend;
58c03c
+		if (!sp_start)
58c03c
+			sp_start = lm->mod_symtable;
58c03c
+
58c03c
+		if ((sp_start >= lm->mod_symtable) && (sp_start < sp_end)) {
58c03c
+			for (sp = sp_start; sp < sp_end; sp++) {
58c03c
+				if (MODULE_START(sp))
58c03c
+					continue;
58c03c
+	
58c03c
+				if (STRNEQ(sp->name, match))
58c03c
+					return sp;
58c03c
+			}
58c03c
+			sp_start = NULL;
58c03c
+		}
58c03c
+	}
58c03c
+
58c03c
+	if (!search_init)
58c03c
+		return NULL;
58c03c
+	
58c03c
+	for (i = 0; i < st->mods_installed; i++) {
58c03c
+		lm = &st->load_modules[i];
58c03c
+		if (!lm->mod_init_symtable)
58c03c
+			continue;
58c03c
+		sp_end = lm->mod_init_symend;
58c03c
+		if (!sp_start)
58c03c
+			sp_start = lm->mod_init_symtable;
58c03c
+
58c03c
+		if ((sp_start >= lm->mod_init_symtable) && (sp_start < sp_end)) {
58c03c
+			for (sp = sp_start; sp < sp_end; sp++) {
58c03c
+				if (MODULE_START(sp))
58c03c
+					continue;
58c03c
+	
58c03c
+				if (STRNEQ(sp->name, match))
58c03c
+					return sp;
58c03c
+			}
58c03c
+		}
58c03c
+	}
58c03c
+
58c03c
+	return NULL;
58c03c
+}