Blob Blame History Raw
[base]

2007-09-21  Jan Kratochvil  <jan.kratochvil@redhat.com>

	* linespec.c (add_minsym_members): Support also the `$allocate' and
	`$delete' variants.

2007-10-05  Jan Kratochvil  <jan.kratochvil@redhat.com>

	* linespec.c (add_minsym_members): Support also the `$allocate' and
	`$delete' variants.
	(decode_variable): Renamed to ...
	(decode_variable_1) ... here, its parameter NOT_FOUND_PTR and its
	exception throwing was moved to ...
	(decode_variable_not_found): ... a new function here.
	(decode_variable): New function.

Index: gdb-6.5/gdb/linespec.c
===================================================================
--- gdb-6.5.orig/gdb/linespec.c	2006-01-10 20:14:43.000000000 -0200
+++ gdb-6.5/gdb/linespec.c	2006-07-07 01:04:56.000000000 -0300
@@ -37,6 +37,7 @@
 #include "objc-lang.h"
 #include "linespec.h"
 #include "exceptions.h"
+#include "gdb_assert.h"
 
 /* We share this one with symtab.c, but it is not exported widely. */
 
@@ -75,7 +75,8 @@ static struct symtabs_and_lines find_met
 					     struct symbol *sym_class);
 
 static int collect_methods (char *copy, struct type *t,
-			    struct symbol **sym_arr);
+			    struct symbol **sym_arr,
+			    struct minimal_symbol **msym_arr);
 
 static NORETURN void cplusplus_error (const char *name,
 				      const char *fmt, ...)
@@ -83,10 +84,12 @@ static NORETURN void cplusplus_error (co
 
 static int total_number_of_methods (struct type *type);
 
-static int find_methods (struct type *, char *, struct symbol **);
+static int find_methods (struct type *, char *, struct symbol **,
+			 struct minimal_symbol **);
 
 static int add_matching_methods (int method_counter, struct type *t,
-				 struct symbol **sym_arr);
+				 struct symbol **sym_arr,
+				 struct minimal_symbol **msym_arr);
 
 static int add_constructors (int method_counter, struct type *t,
 			     struct symbol **sym_arr);
@@ -101,6 +104,9 @@ static int is_objc_method_format (const 
 static struct symtabs_and_lines decode_line_2 (struct symbol *[],
 					       int, int, char ***);
 
+static struct symtabs_and_lines decode_line_3 (struct minimal_symbol *[],
+					       int, int, char ***);
+
 static struct symtab *symtab_from_filename (char **argptr,
 					    char *p, int is_quote_enclosed,
 					    int *not_found_ptr);
@@ -191,12 +197,18 @@ total_number_of_methods (struct type *ty
 /* Recursive helper function for decode_line_1.
    Look for methods named NAME in type T.
    Return number of matches.
-   Put matches in SYM_ARR, which should have been allocated with
+   Put symbol matches in SYM_ARR, which should have been allocated with
    a size of total_number_of_methods (T) * sizeof (struct symbol *).
+   In a special case where we are looking for constructors, we may
+   have to return minimal symbols in the array: MSYM_ARR.  This occurs
+   when the compiler does not generate mangled names for the constructor's
+   debug info because there are multiple versions of the constructor
+   (in-charge vs not-in-charge).
    Note that this function is g++ specific.  */
 
 static int
-find_methods (struct type *t, char *name, struct symbol **sym_arr)
+find_methods (struct type *t, char *name, struct symbol **sym_arr,
+	      struct minimal_symbol **msym_arr)
 {
   int i1 = 0;
   int ibase;
@@ -239,7 +251,8 @@ find_methods (struct type *t, char *name
 	  if (strcmp_iw (name, method_name) == 0)
 	    /* Find all the overloaded methods with that name.  */
 	    i1 += add_matching_methods (method_counter, t,
-					sym_arr + i1);
+					sym_arr + i1,
+					msym_arr);
 	  else if (strncmp (class_name, name, name_len) == 0
 		   && (class_name[name_len] == '\0'
 		       || class_name[name_len] == '<'))
@@ -261,21 +274,101 @@ find_methods (struct type *t, char *name
 
   if (i1 == 0)
     for (ibase = 0; ibase < TYPE_N_BASECLASSES (t); ibase++)
-      i1 += find_methods (TYPE_BASECLASS (t, ibase), name, sym_arr + i1);
+      i1 += find_methods (TYPE_BASECLASS (t, ibase), name, sym_arr + i1,
+			  msym_arr);
 
   return i1;
 }
 
+static int
+add_minsym_members (const char *class_name,
+		    const char *member_name,
+		    struct minimal_symbol **msym_arr)
+{
+  char *completion_name;
+  char **list;
+  int i;
+  int comp_len;
+  int counter = 0;
+
+  /* To find the member, we first cheat and use symbol completion.
+     This will give us a list of all the member names including
+     the function signature.  */
+  completion_name = xmalloc (strlen (class_name) +
+			     strlen (member_name) + 9);
+  completion_name[0] = '\'';
+  strcpy (completion_name+1, class_name);
+  /* FIXME: make this the language class separator.  */
+  strcat (completion_name, "::");
+  strcat (completion_name, member_name);
+  strcat (completion_name, "(");
+  list = make_symbol_completion_list (completion_name,
+				      completion_name+1);
+
+  /* Now that we have the list, we generate an array of their
+     corresponding minimal symbols.  */
+  counter = 0;
+  while (list && list[counter] != NULL)
+    {
+      msym_arr[counter] = lookup_minimal_symbol (list[counter], NULL, NULL);
+      ++counter;
+    }
+
+  xfree (list);
+
+  /* In the case of constructors, there may be in-charge vs not-in-charge
+     constructors.  Check for names with $base which indicates not-in-charge
+     constructors.  */
+  comp_len = strlen (completion_name);
+  strcpy (completion_name + comp_len - 1, "$base(");
+  list = make_symbol_completion_list (completion_name,
+				      completion_name+1);
+
+  /* Again we have a list.  Add their minimal symbols to the array.  */
+  i = 0;
+  while (list && list[i] != NULL)
+    {
+      msym_arr[counter] = lookup_minimal_symbol (list[i++], NULL, NULL);
+      ++counter;
+    }
+  xfree (list);
+
+  /* Target also the allocating/deleting variants.  */
+  if (member_name[0] == '~')
+    strcpy (completion_name + comp_len - 1, "$delete(");
+  else
+    strcpy (completion_name + comp_len - 1, "$allocate(");
+  list = make_symbol_completion_list (completion_name,
+				      completion_name+1);
+
+  /* Again we have a list.  Add their minimal symbols to the array.  */
+  i = 0;
+  while (list && list[i] != NULL)
+    {
+      msym_arr[counter] = lookup_minimal_symbol (list[i++], NULL, NULL);
+      ++counter;
+    }
+  xfree (list);
+
+  xfree (completion_name);
+
+  return counter;
+}
+
 /* Add the symbols associated to methods of the class whose type is T
    and whose name matches the method indexed by METHOD_COUNTER in the
    array SYM_ARR.  Return the number of methods added.  */
 
 static int
 add_matching_methods (int method_counter, struct type *t,
-		      struct symbol **sym_arr)
+		      struct symbol **sym_arr,
+		      struct minimal_symbol **msym_arr)
 {
   int field_counter;
   int i1 = 0;
+  int cons_index = 0;
+  char *class_name = type_name_no_tag (t);
+  char **list = NULL;
 
   for (field_counter = TYPE_FN_FIELDLIST_LENGTH (t, method_counter) - 1;
        field_counter >= 0;
@@ -299,6 +374,16 @@ add_matching_methods (int method_counter
 	}
       else
 	phys_name = TYPE_FN_FIELD_PHYSNAME (f, field_counter);
+
+      /* Check for special case of looking for member that
+	 doesn't have a mangled name provided.  This will happen
+	 when we have in-charge and not-in-charge constructors.
+	 Since we don't have a mangled name to work with, if we
+	 look for the symbol, we can only find the class itself.
+	 We can find the information we need in the minimal symbol
+	 table which has the full member name information we need.  */
+      if (strlen (phys_name) <= strlen (class_name))
+	return add_minsym_members (class_name, phys_name, msym_arr);
 		
       /* Destructor is handled by caller, don't add it to
 	 the list.  */
@@ -324,6 +409,9 @@ add_matching_methods (int method_counter
 	}
     }
 
+  if (list)
+    xfree (list);
+
   return i1;
 }
 
@@ -603,6 +691,146 @@ decode_line_2 (struct symbol *sym_arr[],
   discard_cleanups (old_chain);
   return return_values;
 }
+
+/* Given a list of NELTS minimal symbols in MSYM_ARR, return a list of lines to
+   operate on (ask user if necessary).
+   If CANONICAL is non-NULL return a corresponding array of mangled names
+   as canonical line specs there.  */
+
+static struct symtabs_and_lines
+decode_line_3 (struct minimal_symbol *msym_arr[],
+	       int nelts, int funfirstline,
+	       char ***canonical)
+{
+  struct symtabs_and_lines values, return_values;
+  char *args, *arg1;
+  int i;
+  char *prompt;
+  char *symname;
+  struct cleanup *old_chain;
+  char **canonical_arr = (char **) NULL;
+
+  values.sals = (struct symtab_and_line *)
+    alloca (nelts * sizeof (struct symtab_and_line));
+  return_values.sals = (struct symtab_and_line *)
+    xmalloc (nelts * sizeof (struct symtab_and_line));
+  old_chain = make_cleanup (xfree, return_values.sals);
+
+  if (canonical)
+    {
+      canonical_arr = (char **) xmalloc (nelts * sizeof (char *));
+      make_cleanup (xfree, canonical_arr);
+      memset (canonical_arr, 0, nelts * sizeof (char *));
+      *canonical = canonical_arr;
+    }
+
+  i = 0;
+  printf_unfiltered ("[0] cancel\n[1] all\n");
+  while (i < nelts)
+    {
+      init_sal (&return_values.sals[i]);	/* Initialize to zeroes.  */
+      init_sal (&values.sals[i]);
+      if (msym_arr[i])
+	{
+	  struct symtabs_and_lines msal = minsym_found (funfirstline,
+						        msym_arr[i]);
+	  memcpy (&values.sals[i], &msal.sals[0],
+		  sizeof (struct symtab_and_line));
+	  if (values.sals[i].symtab)
+	    printf_unfiltered ("[%d] %s at %s:%d\n",
+			       (i + 2),
+			       SYMBOL_PRINT_NAME (msym_arr[i]),
+			       values.sals[i].symtab->filename,
+			       values.sals[i].line);
+	  else
+	    printf_unfiltered ("[%d] %s at ?FILE:%d [No symtab? Probably broken debug info...]\n",
+			       (i + 2),
+			       SYMBOL_PRINT_NAME (msym_arr[i]),
+			       values.sals[i].line);
+
+	}
+      else
+	printf_unfiltered ("?HERE\n");
+      i++;
+    }
+
+  prompt = getenv ("PS2");
+  if (prompt == NULL)
+    {
+      prompt = "> ";
+    }
+  args = command_line_input (prompt, 0, "overload-choice");
+
+  if (args == 0 || *args == 0)
+    error_no_arg ("one or more choice numbers");
+
+  i = 0;
+  while (*args)
+    {
+      int num;
+
+      arg1 = args;
+      while (*arg1 >= '0' && *arg1 <= '9')
+	arg1++;
+      if (*arg1 && *arg1 != ' ' && *arg1 != '\t')
+	error ("Arguments must be choice numbers.");
+
+      num = atoi (args);
+
+      if (num == 0)
+	error ("canceled");
+      else if (num == 1)
+	{
+	  if (canonical_arr)
+	    {
+	      for (i = 0; i < nelts; i++)
+		{
+		  if (canonical_arr[i] == NULL)
+		    {
+		      symname = DEPRECATED_SYMBOL_NAME (msym_arr[i]);
+		      canonical_arr[i] = savestring (symname, strlen (symname));
+		    }
+		}
+	    }
+	  memcpy (return_values.sals, values.sals,
+		  (nelts * sizeof (struct symtab_and_line)));
+	  return_values.nelts = nelts;
+	  discard_cleanups (old_chain);
+	  return return_values;
+	}
+
+      if (num >= nelts + 2)
+	{
+	  printf_unfiltered ("No choice number %d.\n", num);
+	}
+      else
+	{
+	  num -= 2;
+	  if (values.sals[num].pc)
+	    {
+	      if (canonical_arr)
+		{
+		  symname = DEPRECATED_SYMBOL_NAME (msym_arr[num]);
+		  make_cleanup (xfree, symname);
+		  canonical_arr[i] = savestring (symname, strlen (symname));
+		}
+	      return_values.sals[i++] = values.sals[num];
+	      values.sals[num].pc = 0;
+	    }
+	  else
+	    {
+	      printf_unfiltered ("duplicate request for %d ignored.\n", num);
+	    }
+	}
+
+      args = arg1;
+      while (*args == ' ' || *args == '\t')
+	args++;
+    }
+  return_values.nelts = i;
+  discard_cleanups (old_chain);
+  return return_values;
+}
 
 /* The parser of linespec itself. */
 
@@ -1406,36 +1634,46 @@ find_method (int funfirstline, char ***c
   int i1;	/*  Counter for the symbol array.  */
   struct symbol **sym_arr =  alloca (total_number_of_methods (t)
 				     * sizeof (struct symbol *));
+  struct minimal_symbol **msym_arr =  alloca (total_number_of_methods (t)
+				     * sizeof (struct minimal_symbol *));
+
+  msym_arr[0] = NULL;
 
   /* Find all methods with a matching name, and put them in
      sym_arr.  */
 
-  i1 = collect_methods (copy, t, sym_arr);
+  i1 = collect_methods (copy, t, sym_arr, msym_arr);
 
   if (i1 == 1)
     {
       /* There is exactly one field with that name.  */
-      sym = sym_arr[0];
-
-      if (sym && SYMBOL_CLASS (sym) == LOC_BLOCK)
-	{
-	  values.sals = (struct symtab_and_line *)
-	    xmalloc (sizeof (struct symtab_and_line));
-	  values.nelts = 1;
-	  values.sals[0] = find_function_start_sal (sym,
-						    funfirstline);
-	}
+      if (msym_arr[0] != NULL)
+	return minsym_found (funfirstline, msym_arr[0]);
       else
 	{
-	  values.sals = NULL;
-	  values.nelts = 0;
+          sym = sym_arr[0];
+
+          if (sym && SYMBOL_CLASS (sym) == LOC_BLOCK)
+	    {
+	      values.sals = (struct symtab_and_line *)
+	        xmalloc (sizeof (struct symtab_and_line));
+	      values.nelts = 1;
+	      values.sals[0] = find_function_start_sal (sym,
+						        funfirstline);
+   	    }
+          else
+	    {
+	      values.nelts = 0;
+	    }
+          return values;
 	}
-      return values;
     }
   if (i1 > 0)
     {
       /* There is more than one field with that name
 	 (overloaded).  Ask the user which one to use.  */
+      if (msym_arr[0] != NULL)
+        return decode_line_3 (msym_arr, i1, funfirstline, canonical);
       return decode_line_2 (sym_arr, i1, funfirstline, canonical);
     }
   else
@@ -1462,11 +1700,12 @@ find_method (int funfirstline, char ***c
 }
 
 /* Find all methods named COPY in the class whose type is T, and put
-   them in SYM_ARR.  Return the number of methods found.  */
+   them in SYM_ARR or MSYM_ARR.  Return the number of methods found.  */
 
 static int
 collect_methods (char *copy, struct type *t,
-		 struct symbol **sym_arr)
+		 struct symbol **sym_arr,
+		 struct minimal_symbol **msym_arr)
 {
   int i1 = 0;	/*  Counter for the symbol array.  */
 
@@ -1488,7 +1727,7 @@ collect_methods (char *copy, struct type
 	}
     }
   else
-    i1 = find_methods (t, copy, sym_arr);
+    i1 = find_methods (t, copy, sym_arr, msym_arr);
 
   return i1;
 }
@@ -1976,12 +2021,13 @@ decode_dollar (char *copy, int funfirstl
    and do not issue an error message.  */ 
 
 static struct symtabs_and_lines
-decode_variable (char *copy, int funfirstline, char ***canonical,
-		 struct symtab *file_symtab, int *not_found_ptr)
+decode_variable_1 (char *copy, int funfirstline, char ***canonical,
+		   struct symtab *file_symtab)
 {
   struct symbol *sym;
   /* The symtab that SYM was found in.  */
   struct symtab *sym_symtab;
+  struct symtabs_and_lines retval;
 
   struct minimal_symbol *msymbol;
 
@@ -2001,8 +2047,25 @@ decode_variable (char *copy, int funfirs
   msymbol = lookup_minimal_symbol (copy, NULL, NULL);
 
   if (msymbol != NULL)
-    return minsym_found (funfirstline, msymbol);
+    {
+      retval = minsym_found (funfirstline, msymbol);
+
+      /* Create a `filename:linkage_symbol_name' reference.  */
+      if (file_symtab == 0)
+	build_canonical_line_spec (retval.sals, SYMBOL_LINKAGE_NAME (msymbol),
+				   canonical);
+
+      return retval;
+    }
 
+  retval.nelts = 0;
+  retval.sals = NULL;
+  return retval;
+}
+
+static void
+decode_variable_not_found (char *copy, int *not_found_ptr)
+{
   if (!have_full_symbols () &&
       !have_partial_symbols () && !have_minimal_symbols ())
     error (_("No symbol table is loaded.  Use the \"file\" command."));
@@ -2010,6 +2064,132 @@ decode_variable (char *copy, int funfirs
   throw_error (NOT_FOUND_ERROR, _("Function \"%s\" not defined."), copy);
 }
 
+/* Wrapper of DECODE_VARIABLE_1 collecting the results for all the found
+   VARIANTS of the symbol COPY.  */
+
+static struct symtabs_and_lines
+decode_variable (char *copy, int funfirstline, char ***canonical,
+		 struct symtab *file_symtab, int *not_found_ptr)
+{
+  char *src;
+  char *src_point;
+  char *s, *point;
+  /* Keep "" last as the trimming part always matches it.  */
+  const char *variants[] = {"$base","$allocate","$delete",""};
+  int i;
+  char *dst, *dst_point;
+  struct
+    {
+      struct symtabs_and_lines sals;
+      char **canonical;
+    } found[ARRAY_SIZE (variants)];
+  struct symtabs_and_lines retval_sals;
+  char **retval_canonical = NULL;	/* Shut up GCC.  */
+  int filled;
+  int canonicals = 0;	/* Shut up GCC.  */
+
+  src = copy;
+  src_point = strchr (src, '(');
+  if (src_point == NULL)
+    {
+      struct symtabs_and_lines sals;
+
+      sals = decode_variable_1 (src, funfirstline, canonical, file_symtab);
+      if (sals.nelts > 0)
+        return sals;
+      decode_variable_not_found (copy, not_found_ptr);
+      /* NOTREACHED */
+    }
+
+  dst = xmalloc (strlen (src) + strlen ("$allocate") + 1);
+  dst_point = dst + (src_point - src);
+
+  memcpy (dst, src, src_point - src);
+
+  /* Trim out any variant markers there first.  */
+  for (i = 0; i < ARRAY_SIZE (variants); i++)
+    {
+      size_t len = strlen (variants[i]);
+
+      if (dst_point - dst >= len
+	  && memcmp (dst_point - len, variants[i], len) == 0)
+	{
+	  dst_point -= len;
+	  /* In fact it should not be needed here.  */
+	  break;
+	}
+    }
+
+  filled = 0;
+  /* And now try to append all of them.  */
+  for (i = 0; i < ARRAY_SIZE (variants); i++)
+    {
+      size_t len = strlen (variants[i]);
+      struct minimal_symbol *minsym2;
+
+      memcpy (dst_point, variants[i], len);
+      strcpy (dst_point + len, src_point);
+
+      found[i].canonical = NULL;
+      found[i].sals = decode_variable_1 (dst, funfirstline,
+					 (canonical == NULL ? NULL
+							 : &found[i].canonical),
+					 file_symtab);
+      filled += found[i].sals.nelts;
+    }
+  xfree (dst);
+  if (filled == 0)
+    {
+      decode_variable_not_found (copy, not_found_ptr);
+      /* NOTREACHED */
+    }
+
+  retval_sals.nelts = filled;
+  retval_sals.sals = xmalloc (filled * sizeof *retval_sals.sals);
+  if (canonical != NULL)
+    {
+      retval_canonical = xmalloc (filled * sizeof *retval_canonical);
+      canonicals = 0;
+    }
+  filled = 0;
+  for (i = 0; i < ARRAY_SIZE (variants); i++)
+    {
+      memcpy (&retval_sals.sals[filled], found[i].sals.sals,
+              found[i].sals.nelts * sizeof *retval_sals.sals);
+      xfree (found[i].sals.sals);
+      if (canonical != NULL)
+        {
+          if (found[i].canonical == NULL)
+	    memset (&retval_canonical[filled], 0,
+	            found[i].sals.nelts * sizeof *retval_canonical);
+	  else
+	    {
+	      int j;
+
+	      memcpy (&retval_canonical[filled], found[i].canonical,
+		      found[i].sals.nelts * sizeof *retval_canonical);
+	      for (j = 0; j < found[i].sals.nelts; j++)
+	        if (found[i].canonical[j] != NULL)
+		  canonicals++;
+	      xfree (found[i].canonical);
+	    }
+	}
+      filled += found[i].sals.nelts;
+    }
+  gdb_assert (filled == retval_sals.nelts);
+
+  if (canonical != NULL)
+    {
+      if (canonicals != 0)
+	*canonical = retval_canonical;
+      else
+	{
+	  *canonical = NULL;
+	  xfree (retval_canonical);
+	}
+    }
+  return retval_sals;
+}
 
 
 
diff -u -rup gdb-6.6-orig/gdb/Makefile.in gdb-6.6/gdb/Makefile.in
--- gdb-6.6-orig/gdb/Makefile.in	2007-10-05 15:22:37.000000000 +0200
+++ gdb-6.6/gdb/Makefile.in	2007-10-05 16:29:10.000000000 +0200
@@ -2266,7 +2266,7 @@ libunwind-frame.o: libunwind-frame.c $(d
 linespec.o: linespec.c $(defs_h) $(symtab_h) $(frame_h) $(command_h) \
 	$(symfile_h) $(objfiles_h) $(source_h) $(demangle_h) $(value_h) \
 	$(completer_h) $(cp_abi_h) $(parser_defs_h) $(block_h) \
-	$(objc_lang_h) $(linespec_h) $(exceptions_h)
+	$(objc_lang_h) $(linespec_h) $(exceptions_h) $(gdb_assert_h)
 linux-fork.o: linux-fork.c $(defs_h) $(inferior_h) $(regcache_h) $(gdbcmd_h) \
 	$(infcall_h) $(gdb_assert_h) $(gdb_string_h) $(linux_fork_h) \
 	$(linux_nat_h)