Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
From: Tristan Gingold <gingold@adacore.com>
To: Joel Brobecker <brobecker@adacore.com>
Cc: "gdb-patches@sourceware.org ml" <gdb-patches@sourceware.org>
Subject: Re: RFA: [Ada] extract known tasks array parameters from symbol table
Date: Fri, 17 Feb 2012 16:34:00 -0000	[thread overview]
Message-ID: <D09C6752-1B6F-461E-9D79-6919A4134D58@adacore.com> (raw)
In-Reply-To: <20120216171547.GD14803@adacore.com>


On Feb 16, 2012, at 6:15 PM, Joel Brobecker wrote:

>> here is the new version, taking into account your comments:  I have
>> mostly reshaped ada_set_current_inferior_known_tasks_addr, tell me if
>> the new form is ok (and then I will test it more thoroughly).
> 
> Overall, that looks good to me. I see what you mean in terms of
> supporting the stripped runtime (this near duplication is ugly),
> but I don't see an efficient way to avoid it.
> 
> Just one minor comment:
> 
>> @@ -865,27 +848,95 @@ get_known_tasks_addr (const char *name)
>> static void
>> ada_set_current_inferior_known_tasks_addr (struct ada_tasks_inferior_data *data)
> 
> I would change the name of the function since it's doing more and more
> than just setting the address. Something like "set_ada_tasks_inferior_data"
> for instance, or maybe "ada_tasks_inferior_data_sniffer", etc.
> 
> Can you also update the comment to just say that it sets all fields in
> DATA instead of specifying each one? It's a bit more vague, but still
> true nonetheless, and will avoid having to update the comment if we add
> new fields again in the future.

So, like this ?

Tristan.

gdb/
2012-02-13 Tristan Gingold <gingold@adacore.com> 

	* ada-tasks.c (struct ada_tasks_inferior_data): Add
	known_tasks_element and known_tasks_length fields.
	(read_known_tasks_array): Change argument type.  Use pointer type
	and number of elements from DATA.  Adjust.
	(read_known_tasks_list): Likewise.
	(get_known_tasks_addr): Remove.
	(ada_set_current_inferior_known_tasks_addr): Renamed to ...
	(ada_tasks_inferior_data_sniffer): ... this.  Try symtab first.
        Merge former get_known_tasks_addr code.


diff --git a/gdb/ada-tasks.c b/gdb/ada-tasks.c
index 274d83a..2ee573e 100644
--- a/gdb/ada-tasks.c
+++ b/gdb/ada-tasks.c
@@ -215,6 +215,12 @@ struct ada_tasks_inferior_data
      above.  */
   CORE_ADDR known_tasks_addr;
 
+  /* Type of elements of the known task.  Usually a pointer.  */
+  struct type *known_tasks_element;
+
+  /* Number of elements in the known tasks array.  */
+  unsigned int known_tasks_length;
+
   /* When nonzero, this flag indicates that the task_list field
      below is up to date.  When set to zero, the list has either
      not been initialized, or has potentially become stale.  */
@@ -774,24 +780,21 @@ add_ada_task (CORE_ADDR task_id, struct inferior *inf)
    it in the current inferior's TASK_LIST.  Return non-zero upon success.  */
 
 static int
-read_known_tasks_array (CORE_ADDR known_tasks_addr)
+read_known_tasks_array (struct ada_tasks_inferior_data *data)
 {
-  const int target_ptr_byte =
-    gdbarch_ptr_bit (target_gdbarch) / TARGET_CHAR_BIT;
-  const int known_tasks_size = target_ptr_byte * MAX_NUMBER_OF_KNOWN_TASKS;
+  const int target_ptr_byte = TYPE_LENGTH (data->known_tasks_element);
+  const int known_tasks_size = target_ptr_byte * data->known_tasks_length;
   gdb_byte *known_tasks = alloca (known_tasks_size);
   int i;
 
   /* Build a new list by reading the ATCBs from the Known_Tasks array
      in the Ada runtime.  */
-  read_memory (known_tasks_addr, known_tasks, known_tasks_size);
-  for (i = 0; i < MAX_NUMBER_OF_KNOWN_TASKS; i++)
+  read_memory (data->known_tasks_addr, known_tasks, known_tasks_size);
+  for (i = 0; i < data->known_tasks_length; i++)
     {
-      struct type *data_ptr_type =
-        builtin_type (target_gdbarch)->builtin_data_ptr;
       CORE_ADDR task_id =
         extract_typed_address (known_tasks + i * target_ptr_byte,
-			       data_ptr_type);
+			       data->known_tasks_element);
 
       if (task_id != 0)
         add_ada_task (task_id, current_inferior ());
@@ -804,13 +807,10 @@ read_known_tasks_array (CORE_ADDR known_tasks_addr)
    the current inferior's TASK_LIST.  Return non-zero upon success.  */
 
 static int
-read_known_tasks_list (CORE_ADDR known_tasks_addr)
+read_known_tasks_list (struct ada_tasks_inferior_data *data)
 {
-  const int target_ptr_byte =
-    gdbarch_ptr_bit (target_gdbarch) / TARGET_CHAR_BIT;
+  const int target_ptr_byte = TYPE_LENGTH (data->known_tasks_element);
   gdb_byte *known_tasks = alloca (target_ptr_byte);
-  struct type *data_ptr_type =
-    builtin_type (target_gdbarch)->builtin_data_ptr;
   CORE_ADDR task_id;
   const struct ada_tasks_pspace_data *pspace_data
     = get_ada_tasks_pspace_data (current_program_space);
@@ -820,8 +820,8 @@ read_known_tasks_list (CORE_ADDR known_tasks_addr)
     return 0;
 
   /* Build a new list by reading the ATCBs.  Read head of the list.  */
-  read_memory (known_tasks_addr, known_tasks, target_ptr_byte);
-  task_id = extract_typed_address (known_tasks, data_ptr_type);
+  read_memory (data->known_tasks_addr, known_tasks, target_ptr_byte);
+  task_id = extract_typed_address (known_tasks, data->known_tasks_element);
   while (task_id != 0)
     {
       struct value *tcb_value;
@@ -841,51 +841,101 @@ read_known_tasks_list (CORE_ADDR known_tasks_addr)
   return 1;
 }
 
-/* Return the address of the variable NAME that contains all the known
-   tasks maintained in the Ada Runtime.  Return NULL if the variable
-   could not be found, meaning that the inferior program probably does
-   not use tasking.  */
+/* Set all fields of the current inferior ada-tasks data pointed by DATA.
+   Do nothing if those fields are already set and still up to date.  */
 
-static CORE_ADDR
-get_known_tasks_addr (const char *name)
+static void
+ada_tasks_inferior_data_sniffer (struct ada_tasks_inferior_data *data)
 {
+  const char *name;
   struct minimal_symbol *msym;
+  struct symbol *sym;
 
-  msym = lookup_minimal_symbol (name, NULL, NULL);
-  if (msym == NULL)
-    return 0;
+  /* Return now if already set.  */
+  if (data->known_tasks_kind != ADA_TASKS_UNKNOWN)
+    return;
 
-  return SYMBOL_VALUE_ADDRESS (msym);
-}
+  /* First with the symtab, which knows the exact array type and size.  */
 
-/* Assuming DATA is the ada-tasks' data for the current inferior,
-   set the known_tasks_kind and known_tasks_addr fields.  Do nothing
-   if those fields are already set and still up to date.  */
+  /* Try array.  */
 
-static void
-ada_set_current_inferior_known_tasks_addr (struct ada_tasks_inferior_data *data)
-{
-  CORE_ADDR known_tasks_addr;
+  sym = lookup_symbol_in_language (KNOWN_TASKS_NAME, NULL, VAR_DOMAIN,
+				   language_c, NULL);
+  if (sym != NULL)
+    {
+      /* Validate.  */
+      struct type *type = check_typedef (SYMBOL_TYPE (sym));
+      struct type *eltype;
+      struct type *idxtype;
+
+      if (TYPE_CODE (type) == TYPE_CODE_ARRAY
+	  && (eltype = check_typedef (TYPE_TARGET_TYPE (type)))
+	  && TYPE_CODE (eltype) == TYPE_CODE_PTR
+	  && (idxtype = check_typedef (TYPE_INDEX_TYPE (type)))
+	  && !TYPE_LOW_BOUND_UNDEFINED (idxtype)
+	  && !TYPE_HIGH_BOUND_UNDEFINED (idxtype))
+	{
+	  data->known_tasks_kind = ADA_TASKS_ARRAY;
+	  data->known_tasks_addr = SYMBOL_VALUE_ADDRESS (sym);
+	  data->known_tasks_element = eltype;
+	  data->known_tasks_length =
+	    TYPE_HIGH_BOUND (idxtype) - TYPE_LOW_BOUND (idxtype) + 1;
+	  return;
+	}
+    }
 
-  if (data->known_tasks_kind != ADA_TASKS_UNKNOWN)
-    return;
+  /* Try list.  */
 
-  known_tasks_addr = get_known_tasks_addr (KNOWN_TASKS_NAME);
-  if (known_tasks_addr != 0)
+  sym = lookup_symbol_in_language (KNOWN_TASKS_LIST, NULL, VAR_DOMAIN,
+				   language_c, NULL);
+  if (sym != NULL)
+    {
+      /* Validate.  */
+      struct type *type = check_typedef (SYMBOL_TYPE (sym));
+
+      if (TYPE_CODE (type) == TYPE_CODE_PTR)
+	{
+	  data->known_tasks_kind = ADA_TASKS_LIST;
+	  data->known_tasks_addr = SYMBOL_VALUE_ADDRESS (sym);
+	  data->known_tasks_element = type;
+	  data->known_tasks_length = 1;
+	  return;
+	}
+    }
+
+  /* Fallback using the minsymtab.  The runtime may have been stripped (as in
+     some distributions), but it is likely that the executable still contains
+     debug information on the task type (due to implicit with of Ada.Tasking).
+  */
+
+  /* Try array.  */
+
+  msym = lookup_minimal_symbol (KNOWN_TASKS_NAME, NULL, NULL);
+  if (msym != NULL)
     {
       data->known_tasks_kind = ADA_TASKS_ARRAY;
-      data->known_tasks_addr = known_tasks_addr;
+      data->known_tasks_addr = SYMBOL_VALUE_ADDRESS (msym);
+      data->known_tasks_element =
+	builtin_type (target_gdbarch)->builtin_data_ptr;
+      data->known_tasks_length = MAX_NUMBER_OF_KNOWN_TASKS;
       return;
     }
 
-  known_tasks_addr = get_known_tasks_addr (KNOWN_TASKS_LIST);
-  if (known_tasks_addr != 0)
+  /* Try list.  */
+
+  msym = lookup_minimal_symbol (KNOWN_TASKS_LIST, NULL, NULL);
+  if (msym != NULL)
     {
       data->known_tasks_kind = ADA_TASKS_LIST;
-      data->known_tasks_addr = known_tasks_addr;
+      data->known_tasks_addr = SYMBOL_VALUE_ADDRESS (msym);
+      data->known_tasks_element =
+	builtin_type (target_gdbarch)->builtin_data_ptr;
+      data->known_tasks_length = 1;
       return;
     }
 
+  /* Can't find tasks.  */
+
   data->known_tasks_kind = ADA_TASKS_NOT_FOUND;
   data->known_tasks_addr = 0;
 }
@@ -909,7 +959,7 @@ read_known_tasks (void)
      return, as we don't want a stale task list to be used...  This can
      happen for instance when debugging a non-multitasking program after
      having debugged a multitasking one.  */
-  ada_set_current_inferior_known_tasks_addr (data);
+  ada_tasks_inferior_data_sniffer (data);
   gdb_assert (data->known_tasks_kind != ADA_TASKS_UNKNOWN);
 
   switch (data->known_tasks_kind)
@@ -917,9 +967,9 @@ read_known_tasks (void)
       case ADA_TASKS_NOT_FOUND: /* Tasking not in use in inferior.  */
         return 0;
       case ADA_TASKS_ARRAY:
-        return read_known_tasks_array (data->known_tasks_addr);
+        return read_known_tasks_array (data);
       case ADA_TASKS_LIST:
-        return read_known_tasks_list (data->known_tasks_addr);
+        return read_known_tasks_list (data);
     }
 
   /* Step 3: Set task_list_valid_p, to avoid re-reading the Known_Tasks


  reply	other threads:[~2012-02-17 16:10 UTC|newest]

Thread overview: 12+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-02-13 15:14 Tristan Gingold
2012-02-13 16:16 ` Joel Brobecker
2012-02-14  8:19   ` Tristan Gingold
2012-02-14 15:47     ` Joel Brobecker
2012-02-16 14:40   ` Tristan Gingold
2012-02-16 17:19     ` Joel Brobecker
2012-02-17 16:34       ` Tristan Gingold [this message]
2012-02-17 16:37         ` Joel Brobecker
2012-02-17 19:23           ` Tristan Gingold
2012-02-20 17:11           ` Tristan Gingold
2012-02-21 18:16             ` Joel Brobecker
2012-02-23 16:34               ` Tristan Gingold

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=D09C6752-1B6F-461E-9D79-6919A4134D58@adacore.com \
    --to=gingold@adacore.com \
    --cc=brobecker@adacore.com \
    --cc=gdb-patches@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox