This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[3/3] RFC: `function:label' linespecs


This patch adds support for `function:label' linespecs.

I think it is reasonably straightforward now that the infrastructure is
in place.  Label linespecs of all kinds are given `function:label' as
their canonical form.  Per an earlier discussion on the list, I changed
the code to use the label's PC, rather than its line, when constructing
the SAL.

This, combined with patches #1 and #2, was built and regtested on x86-64
(compile farm).

Documentation update and new tests included.

Tom

2011-03-18  Tom Tromey  <tromey@redhat.com>

	PR breakpoints/11816:
	* linespec.c (decode_line_1): Parse `function:label' linespecs.
	(decode_compound): Update.
	(find_function_symbol): New function.
	(decode_dollar): Update.
	(decode_label): Add 'function_symbol' parameter.  Handle
	function-relative labels.
	(decode_variable): Update.
	(symbol_found): Add 'function_symbol' parameter.  Use label's PC,
	not its line.  Set `special_display' and canonical name for
	labels.

2011-03-18  Tom Tromey  <tromey@redhat.com>

	* gdb.texinfo (Specify Location): Document `function:label'
	linespec.

2011-03-18  Tom Tromey  <tromey@redhat.com>

	* gdb.base/label.exp: Use `main:there' linespec.  Add re-running
	test.

diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index ea1e2f5..68b8f79 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -6361,6 +6361,10 @@ Specifies the line @var{linenum} in the source file @var{filename}.
 Specifies the line that begins the body of the function @var{function}.
 For example, in C, this is the line with the open brace.
 
+@item @var{function}:@var{label}
+Specifies the line at which the label named @var{label} appears in the
+function named @var{function}.
+
 @item @var{filename}:@var{function}
 Specifies the line that begins the body of the function @var{function}
 in the file @var{filename}.  You only need the file name with a
diff --git a/gdb/linespec.c b/gdb/linespec.c
index 6c0e7ed..d079ae0 100644
--- a/gdb/linespec.c
+++ b/gdb/linespec.c
@@ -111,6 +111,9 @@ static struct symtab *symtab_from_filename (char **argptr,
 					    char *p, int is_quote_enclosed,
 					    int *not_found_ptr);
 
+static struct symbol *find_function_symbol (char **argptr, char *p,
+					    int is_quote_enclosed);
+
 static struct
 symtabs_and_lines decode_all_digits (char **argptr,
 				     struct symtab *default_symtab,
@@ -125,7 +128,8 @@ static struct symtabs_and_lines decode_dollar (char *copy,
 					       struct linespec_result *canonical,
 					       struct symtab *file_symtab);
 
-static int decode_label (char *copy, struct linespec_result *canonical,
+static int decode_label (struct symbol *function_symbol,
+			 char *copy, struct linespec_result *canonical,
 			 struct symtabs_and_lines *result);
 
 static struct symtabs_and_lines decode_variable (char *copy,
@@ -139,7 +143,8 @@ symtabs_and_lines symbol_found (int funfirstline,
 				struct linespec_result *canonical,
 				char *copy,
 				struct symbol *sym,
-				struct symtab *file_symtab);
+				struct symtab *file_symtab,
+				struct symbol *function_symbol);
 
 static struct
 symtabs_and_lines minsym_found (int funfirstline,
@@ -813,6 +818,13 @@ decode_line_1 (char **argptr, int funfirstline, struct symtab *default_symtab,
   /* The "first half" of the linespec.  */
   char *first_half;
 
+  /* If we are parsing `function:label', this holds the symbol for the
+     function.  */
+  struct symbol *function_symbol = NULL;
+  /* If FUNCTION_SYMBOL is not NULL, then this is the exception that
+     was thrown when trying to parse a filename.  */
+  volatile struct gdb_exception file_exception;
+
   if (not_found_ptr)
     *not_found_ptr = 0;
 
@@ -885,8 +897,22 @@ decode_line_1 (char **argptr, int funfirstline, struct symtab *default_symtab,
       /* No, the first part is a filename; set file_symtab to be that file's
 	 symtab.  Also, move argptr past the filename.  */
 
-      file_symtab = symtab_from_filename (argptr, p, is_quote_enclosed,
-					  not_found_ptr);
+      TRY_CATCH (file_exception, RETURN_MASK_ERROR)
+	{
+	  file_symtab = symtab_from_filename (argptr, p, is_quote_enclosed,
+					      not_found_ptr);
+	}
+      /* If that failed, maybe we have `function:label'.  */
+      if (file_exception.reason < 0)
+	{
+	  function_symbol = find_function_symbol (argptr, p, is_quote_enclosed);
+	  /* If we did not find a function, re-throw the original
+	     exception.  */
+	  if (!function_symbol)
+	    throw_exception (file_exception);
+	  if (not_found_ptr)
+	    *not_found_ptr = 0;
+	}
 
       /* Check for single quotes on the non-filename part.  */
       if (!is_quoted)
@@ -900,6 +926,8 @@ decode_line_1 (char **argptr, int funfirstline, struct symtab *default_symtab,
     }
 
   /* file_symtab is specified file's symtab, or 0 if no file specified.
+     If we are parsing `function:symbol', then FUNCTION_SYMBOL is the
+     function before the `:'.
      arg no longer contains the file name.  */
 
   /* If the filename was quoted, we must re-check the quotation.  */
@@ -921,7 +949,8 @@ decode_line_1 (char **argptr, int funfirstline, struct symtab *default_symtab,
   while (*q >= '0' && *q <= '9')
     q++;
 
-  if (q != *argptr && (*q == 0 || *q == ' ' || *q == '\t' || *q == ','))
+  if (q != *argptr && (*q == 0 || *q == ' ' || *q == '\t' || *q == ',')
+      && function_symbol == NULL)
     /* We found a token consisting of all digits -- at least one digit.  */
     return decode_all_digits (argptr, default_symtab, default_line,
 			      canonical, file_symtab, q);
@@ -972,7 +1001,7 @@ decode_line_1 (char **argptr, int funfirstline, struct symtab *default_symtab,
      (e.g. HP-UX millicode routines such as $$dyncall), or it may
      be history value, or it may be a convenience variable.  */
 
-  if (*copy == '$')
+  if (*copy == '$' && function_symbol == NULL)
     return decode_dollar (copy, funfirstline, default_symtab,
 			  canonical, file_symtab);
 
@@ -982,10 +1011,17 @@ decode_line_1 (char **argptr, int funfirstline, struct symtab *default_symtab,
   if (!file_symtab)
     {
       struct symtabs_and_lines label_result;
-      if (decode_label (copy, canonical, &label_result))
+      if (decode_label (function_symbol, copy, canonical, &label_result))
 	return label_result;
     }
 
+  if (function_symbol)
+    {
+      if (not_found_ptr)
+	*not_found_ptr = 1;
+      throw_exception (file_exception);
+    }
+
   /* Look up that token as a variable.
      If file specified, use that file's per-file block to start with.  */
 
@@ -1573,7 +1609,7 @@ decode_compound (char **argptr, int funfirstline,
   /* Look up entire name.  */
   sym = lookup_symbol (copy, get_selected_block (0), VAR_DOMAIN, 0);
   if (sym)
-    return symbol_found (funfirstline, canonical, copy, sym, NULL);
+    return symbol_found (funfirstline, canonical, copy, sym, NULL, NULL);
   else
     {
       struct minimal_symbol *msym;
@@ -1811,6 +1847,44 @@ symtab_from_filename (char **argptr, char *p, int is_quote_enclosed,
   return file_symtab;
 }
 
+/* Look up a function symbol in *ARGPTR.  If found, advance *ARGPTR
+   and return the symbol.  If not found, return NULL.  */
+
+static struct symbol *
+find_function_symbol (char **argptr, char *p, int is_quote_enclosed)
+{
+  char *p1;
+  char *copy;
+  struct symbol *function_symbol;
+
+  p1 = p;
+  while (p != *argptr && p[-1] == ' ')
+    --p;
+  if ((*p == '"') && is_quote_enclosed)
+    --p;
+  copy = (char *) alloca (p - *argptr + 1);
+  memcpy (copy, *argptr, p - *argptr);
+  /* It may have the ending quote right after the file name.  */
+  if ((is_quote_enclosed && copy[p - *argptr - 1] == '"')
+      || copy[p - *argptr - 1] == '\'')
+    copy[p - *argptr - 1] = 0;
+  else
+    copy[p - *argptr] = 0;
+
+  function_symbol = lookup_symbol (copy, get_selected_block (0),
+				   VAR_DOMAIN, 0);
+  if (!function_symbol || SYMBOL_CLASS (function_symbol) != LOC_BLOCK)
+    return NULL;
+
+  /* Discard the file name from the arg.  */
+  p = p1 + 1;
+  while (*p == ' ' || *p == '\t')
+    p++;
+  *argptr = p;
+
+  return function_symbol;
+}
+
 
 
 /* This decodes a line where the argument is all digits (possibly
@@ -1945,7 +2019,7 @@ decode_dollar (char *copy, int funfirstline, struct symtab *default_symtab,
       need_canonical = 1;
       /* Symbol was found --> jump to normal symbol processing.  */
       if (sym)
-	return symbol_found (funfirstline, canonical, copy, sym, NULL);
+	return symbol_found (funfirstline, canonical, copy, sym, NULL, NULL);
 
       /* If symbol was not found, look in minimal symbol tables.  */
       msymbol = lookup_minimal_symbol (copy, NULL, NULL);
@@ -1981,6 +2055,8 @@ decode_dollar (char *copy, int funfirstline, struct symtab *default_symtab,
 
 /* A helper for decode_line_1 that tries to find a label.  The label
    is searched for in the current block.
+   FUNCTION_SYMBOL is the enclosing function; or NULL if none
+   specified.
    COPY is the name of the label to find.
    CANONICAL is the same as the "canonical" argument to decode_line_1.
    RESULT is a pointer to a symtabs_and_lines structure which will be
@@ -1988,15 +2064,31 @@ decode_dollar (char *copy, int funfirstline, struct symtab *default_symtab,
    This function returns 1 if a label was found, 0 otherwise.  */
 
 static int
-decode_label (char *copy, struct linespec_result *canonical,
+decode_label (struct symbol *function_symbol, char *copy,
+	      struct linespec_result *canonical,
 	      struct symtabs_and_lines *result)
 {
   struct symbol *sym;
+  struct block *block;
+
+  if (function_symbol)
+    block = SYMBOL_BLOCK_VALUE (function_symbol);
+  else
+    {
+      block = get_selected_block (0);
+      for (;
+	   block && !BLOCK_FUNCTION (block);
+	   block = BLOCK_SUPERBLOCK (block))
+	;
+      if (!block)
+	return 0;
+      function_symbol = BLOCK_FUNCTION (block);
+    }
 
-  sym = lookup_symbol (copy, get_selected_block (0), LABEL_DOMAIN, 0);
+  sym = lookup_symbol (copy, block, LABEL_DOMAIN, 0);
 
   if (sym != NULL)
-    *result = symbol_found (0, canonical, copy, sym, NULL);
+    *result = symbol_found (0, canonical, copy, sym, NULL, function_symbol);
 
   return sym != NULL;
 }
@@ -2022,7 +2114,7 @@ decode_variable (char *copy, int funfirstline,
 		       VAR_DOMAIN, 0);
 
   if (sym != NULL)
-    return symbol_found (funfirstline, canonical, copy, sym, file_symtab);
+    return symbol_found (funfirstline, canonical, copy, sym, file_symtab, NULL);
 
   msymbol = lookup_minimal_symbol (copy, NULL, NULL);
 
@@ -2051,7 +2143,8 @@ decode_variable (char *copy, int funfirstline,
 
 static struct symtabs_and_lines
 symbol_found (int funfirstline, struct linespec_result *canonical, char *copy,
-	      struct symbol *sym, struct symtab *file_symtab)
+	      struct symbol *sym, struct symtab *file_symtab,
+	      struct symbol *function_symbol)
 {
   struct symtabs_and_lines values;
   
@@ -2083,16 +2176,29 @@ symbol_found (int funfirstline, struct linespec_result *canonical, char *copy,
     {
       if (funfirstline && SYMBOL_CLASS (sym) != LOC_LABEL)
 	error (_("\"%s\" is not a function"), copy);
-      else if (SYMBOL_LINE (sym) != 0)
+      else if (SYMBOL_VALUE_ADDRESS (sym) != 0)
 	{
 	  /* We know its line number.  */
 	  values.sals = (struct symtab_and_line *)
 	    xmalloc (sizeof (struct symtab_and_line));
 	  values.nelts = 1;
-	  memset (&values.sals[0], 0, sizeof (values.sals[0]));
+	  init_sal (&values.sals[0]);
 	  values.sals[0].symtab = SYMBOL_SYMTAB (sym);
 	  values.sals[0].line = SYMBOL_LINE (sym);
+	  values.sals[0].pc = SYMBOL_VALUE_ADDRESS (sym);
 	  values.sals[0].pspace = SYMTAB_PSPACE (SYMBOL_SYMTAB (sym));
+	  values.sals[0].explicit_pc = 1;
+
+	  if (canonical)
+	    {
+	      canonical->special_display = 1;
+	      canonical->canonical = xmalloc (sizeof (char *));
+	      canonical->canonical[0]
+		= xstrprintf ("%s:%s",
+			      SYMBOL_NATURAL_NAME (function_symbol),
+			      SYMBOL_NATURAL_NAME (sym));
+	    }
+
 	  return values;
 	}
       else
diff --git a/gdb/testsuite/gdb.base/label.exp b/gdb/testsuite/gdb.base/label.exp
index de6aaf7..be23738 100644
--- a/gdb/testsuite/gdb.base/label.exp
+++ b/gdb/testsuite/gdb.base/label.exp
@@ -46,7 +46,7 @@ gdb_test "break here" \
   "Breakpoint.*at.*" \
   "breakpoint here"
 
-gdb_test "break there" \
+gdb_test "break main:there" \
   "Breakpoint.*at.*" \
   "breakpoint there"
 
@@ -57,3 +57,9 @@ gdb_test "cont" \
 gdb_test "cont" \
   "Breakpoint 2,.*" \
   "continue to 'here'"
+
+rerun_to_main
+
+gdb_test "cont" \
+  "Breakpoint 3,.*" \
+  "continue to 'there' after re-run"


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]