Handle CPU offset for Ravenscar
authorTom Tromey <tromey@adacore.com>
Tue, 17 Nov 2020 18:25:02 +0000 (11:25 -0700)
committerTom Tromey <tromey@adacore.com>
Fri, 11 Dec 2020 15:01:47 +0000 (08:01 -0700)
The Ravenscar support assumes that the thread ID is the same as the
CPU ID that appears in the Ada task structure.  However, on some
systems, gdbserver will report thread IDs that are off by some
constant.  This can happen, e.g., with qemu in a scenario where there
is an additional (unreported) CPU in the emulation.

The Ada Ravenscar runtimes have been modified to store this offset in
a global variable.  This patch changes gdb to read this variable, when
it exists, and apply the offset to the base CPU ID.  This fixes some
crashes that otherwise occur.

2020-12-11  Tom Tromey  <tromey@adacore.com>

* ada-tasks.c (struct ada_tasks_pspace_data) <cpu_id_offset>: New
field.
(ada_get_tcb_types_info): Look for __gnat_gdb_cpu_first_id.
(read_atcb): Use cpu_id_offset.

gdb/ChangeLog
gdb/ada-tasks.c

index 79e84bc41807d384c744d0b033bbcc9f9aa6cc26..4533a6a7b8b9f215d25cdd07f0ea345848fc443c 100644 (file)
@@ -1,3 +1,10 @@
+2020-12-11  Tom Tromey  <tromey@adacore.com>
+
+       * ada-tasks.c (struct ada_tasks_pspace_data) <cpu_id_offset>: New
+       field.
+       (ada_get_tcb_types_info): Look for __gnat_gdb_cpu_first_id.
+       (read_atcb): Use cpu_id_offset.
+
 2020-12-10  Kevin Buettner  <kevinb@redhat.com>
 
        * ada-lang.c (ada_fold_name): Fix off-by-one error.
index c66d08f92fa76b564b6d87c0fe5916d0ef11bcb8..151490676090c82d8310a77685ae81155bdab3f9 100644 (file)
@@ -159,6 +159,10 @@ struct ada_tasks_pspace_data
 
   /* The index of various fields in the ATCB record and sub-records.  */
   struct atcb_fieldnos atcb_fieldno {};
+
+  /* On some systems, gdbserver applies an offset to the CPU that is
+     reported.  */
+  unsigned int cpu_id_offset = 0;
 };
 
 /* Key to our per-program-space data.  */
@@ -564,6 +568,18 @@ ada_get_tcb_types_info (void)
   if (fieldnos.ll_lwp < 0)
     fieldnos.ll_lwp = ada_get_field_index (ll_type, "thread_id", 1);
 
+  /* Check for the CPU offset.  */
+  bound_minimal_symbol first_id_sym
+    = lookup_bound_minimal_symbol ("__gnat_gdb_cpu_first_id");
+  unsigned int first_id = 0;
+  if (first_id_sym.minsym != nullptr)
+    {
+      CORE_ADDR addr = BMSYMBOL_VALUE_ADDRESS (first_id_sym);
+      /* This symbol always has type uint32_t.  */
+      struct type *u32type = builtin_type (target_gdbarch ())->builtin_uint32;
+      first_id = value_as_long (value_at (u32type, addr));
+    }
+
   /* Set all the out parameters all at once, now that we are certain
      that there are no potential error() anymore.  */
   pspace_data = get_ada_tasks_pspace_data (current_program_space);
@@ -573,6 +589,7 @@ ada_get_tcb_types_info (void)
   pspace_data->atcb_ll_type = ll_type;
   pspace_data->atcb_call_type = call_type;
   pspace_data->atcb_fieldno = fieldnos;
+  pspace_data->cpu_id_offset = first_id;
   return NULL;
 }
 
@@ -769,8 +786,9 @@ read_atcb (CORE_ADDR task_id, struct ada_task_info *task_info)
     }
 
   task_info->base_cpu
-    = value_as_long (value_field (common_value,
-                                 pspace_data->atcb_fieldno.base_cpu));
+    = (pspace_data->cpu_id_offset
+      + value_as_long (value_field (common_value,
+                                   pspace_data->atcb_fieldno.base_cpu)));
 
   /* And finally, compute the task ptid.  Note that there is not point
      in computing it if the task is no longer alive, in which case