Automatic Copyright Year update after running gdb/copyright.py
[deliverable/binutils-gdb.git] / gdb / ravenscar-thread.c
CommitLineData
036b1ba8
JB
1/* Ada Ravenscar thread support.
2
88b9d363 3 Copyright (C) 2004-2022 Free Software Foundation, Inc.
036b1ba8
JB
4
5 This file is part of GDB.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
19
20#include "defs.h"
21#include "gdbcore.h"
22#include "gdbthread.h"
23#include "ada-lang.h"
24#include "target.h"
25#include "inferior.h"
26#include "command.h"
27#include "ravenscar-thread.h"
76727919 28#include "observable.h"
036b1ba8
JB
29#include "gdbcmd.h"
30#include "top.h"
31#include "regcache.h"
77e371c0 32#include "objfiles.h"
a8ac85bb 33#include <unordered_map>
036b1ba8 34
9edcc12f
JB
35/* This module provides support for "Ravenscar" tasks (Ada) when
36 debugging on bare-metal targets.
37
38 The typical situation is when debugging a bare-metal target over
39 the remote protocol. In that situation, the system does not know
e397fd39 40 about high-level concepts such as threads, only about some code
9edcc12f
JB
41 running on one or more CPUs. And since the remote protocol does not
42 provide any handling for CPUs, the de facto standard for handling
43 them is to have one thread per CPU, where the thread's ptid has
44 its lwp field set to the CPU number (eg: 1 for the first CPU,
45 2 for the second one, etc). This module will make that assumption.
46
47 This module then creates and maintains the list of threads based
e397fd39 48 on the list of Ada tasks, with one thread per Ada task. The convention
9edcc12f 49 is that threads corresponding to the CPUs (see assumption above)
e397fd39 50 have a ptid_t of the form (PID, LWP, 0), while threads corresponding
9edcc12f
JB
51 to our Ada tasks have a ptid_t of the form (PID, 0, TID) where TID
52 is the Ada task's ID as extracted from Ada runtime information.
53
e397fd39
TT
54 Switching to a given Ada task (or its underlying thread) is performed
55 by fetching the registers of that task from the memory area where
9edcc12f
JB
56 the registers were saved. For any of the other operations, the
57 operation is performed by first finding the CPU on which the task
58 is running, switching to its corresponding ptid, and then performing
59 the operation on that ptid using the target beneath us. */
60
491144b5
CB
61/* If true, ravenscar task support is enabled. */
62static bool ravenscar_task_support = true;
036b1ba8 63
7f39f34a 64static const char running_thread_name[] = "__gnat_running_thread_table";
036b1ba8
JB
65
66static const char known_tasks_name[] = "system__tasking__debug__known_tasks";
6040a59d 67static const char first_task_name[] = "system__tasking__debug__first_task";
036b1ba8 68
6cbcc006
TT
69static const char ravenscar_runtime_initializer[]
70 = "system__bb__threads__initialize";
036b1ba8 71
d9f719f1
PA
72static const target_info ravenscar_target_info = {
73 "ravenscar",
74 N_("Ravenscar tasks."),
75 N_("Ravenscar tasks support.")
76};
77
f6ac5f3d
PA
78struct ravenscar_thread_target final : public target_ops
79{
0b790b1e 80 ravenscar_thread_target ()
2da4b788 81 : m_base_ptid (inferior_ptid)
0b790b1e 82 {
0b790b1e
TT
83 }
84
d9f719f1
PA
85 const target_info &info () const override
86 { return ravenscar_target_info; }
f6ac5f3d 87
66b4deae
PA
88 strata stratum () const override { return thread_stratum; }
89
b60cea74 90 ptid_t wait (ptid_t, struct target_waitstatus *, target_wait_flags) override;
f6ac5f3d
PA
91 void resume (ptid_t, int, enum gdb_signal) override;
92
93 void fetch_registers (struct regcache *, int) override;
94 void store_registers (struct regcache *, int) override;
95
96 void prepare_to_store (struct regcache *) override;
97
57810aa7 98 bool stopped_by_sw_breakpoint () override;
f6ac5f3d 99
57810aa7 100 bool stopped_by_hw_breakpoint () override;
f6ac5f3d 101
57810aa7 102 bool stopped_by_watchpoint () override;
f6ac5f3d 103
57810aa7 104 bool stopped_data_address (CORE_ADDR *) override;
f6ac5f3d 105
2080266b
TT
106 enum target_xfer_status xfer_partial (enum target_object object,
107 const char *annex,
108 gdb_byte *readbuf,
109 const gdb_byte *writebuf,
110 ULONGEST offset, ULONGEST len,
111 ULONGEST *xfered_len) override;
112
57810aa7 113 bool thread_alive (ptid_t ptid) override;
f6ac5f3d
PA
114
115 int core_of_thread (ptid_t ptid) override;
116
117 void update_thread_list () override;
118
a068643d 119 std::string pid_to_str (ptid_t) override;
f6ac5f3d
PA
120
121 ptid_t get_ada_task_ptid (long lwp, long thread) override;
122
2080266b
TT
123 struct btrace_target_info *enable_btrace (ptid_t ptid,
124 const struct btrace_config *conf)
125 override
126 {
127 ptid = get_base_thread_from_ravenscar_task (ptid);
128 return beneath ()->enable_btrace (ptid, conf);
129 }
130
f6ac5f3d 131 void mourn_inferior () override;
f6ac5f3d 132
0b790b1e
TT
133 void close () override
134 {
135 delete this;
136 }
137
3d4470e5
TT
138 thread_info *add_active_thread ();
139
0b790b1e 140private:
f6ac5f3d 141
0b790b1e
TT
142 /* PTID of the last thread that received an event.
143 This can be useful to determine the associated task that received
144 the event, to make it the current task. */
2da4b788 145 ptid_t m_base_ptid;
0b790b1e 146
0b790b1e
TT
147 ptid_t active_task (int cpu);
148 bool task_is_currently_active (ptid_t ptid);
149 bool runtime_initialized ();
a8ac85bb
TT
150 int get_thread_base_cpu (ptid_t ptid);
151 ptid_t get_base_thread_from_ravenscar_task (ptid_t ptid);
2080266b 152 void add_thread (struct ada_task_info *task);
a8ac85bb 153
a52b3ae2
TT
154 /* Like switch_to_thread, but uses the base ptid for the thread. */
155 void set_base_thread_from_ravenscar_task (ptid_t ptid)
156 {
157 process_stratum_target *proc_target
158 = as_process_stratum_target (this->beneath ());
159 ptid_t underlying = get_base_thread_from_ravenscar_task (ptid);
160 switch_to_thread (find_thread_ptid (proc_target, underlying));
161 }
162
a8ac85bb
TT
163 /* This maps a TID to the CPU on which it was running. This is
164 needed because sometimes the runtime will report an active task
165 that hasn't yet been put on the list of tasks that is read by
166 ada-tasks.c. */
167 std::unordered_map<long, int> m_cpu_map;
0b790b1e 168};
036b1ba8 169
989f3c58 170/* Return true iff PTID corresponds to a ravenscar task. */
9edcc12f 171
989f3c58 172static bool
9edcc12f
JB
173is_ravenscar_task (ptid_t ptid)
174{
54aa6c67
JB
175 /* By construction, ravenscar tasks have their LWP set to zero.
176 Also make sure that the TID is nonzero, as some remotes, when
177 asked for the list of threads, will return the first thread
178 as having its TID set to zero. For instance, TSIM version
179 2.0.48 for LEON3 sends 'm0' as a reply to the 'qfThreadInfo'
180 query, which the remote protocol layer then treats as a thread
181 whose TID is 0. This is obviously not a ravenscar task. */
cc6bcb54 182 return ptid.lwp () == 0 && ptid.tid () != 0;
9edcc12f
JB
183}
184
185/* Given PTID, which can be either a ravenscar task or a CPU thread,
186 return which CPU that ptid is running on.
187
188 This assume that PTID is a valid ptid_t. Otherwise, a gdb_assert
189 will be triggered. */
190
a8ac85bb
TT
191int
192ravenscar_thread_target::get_thread_base_cpu (ptid_t ptid)
9edcc12f
JB
193{
194 int base_cpu;
195
196 if (is_ravenscar_task (ptid))
197 {
2080266b
TT
198 /* Prefer to not read inferior memory if possible, to avoid
199 reentrancy problems with xfer_partial. */
200 auto iter = m_cpu_map.find (ptid.tid ());
9edcc12f 201
2080266b
TT
202 if (iter != m_cpu_map.end ())
203 base_cpu = iter->second;
a8ac85bb
TT
204 else
205 {
2080266b 206 struct ada_task_info *task_info = ada_get_task_info_from_ptid (ptid);
a8ac85bb 207
2080266b
TT
208 gdb_assert (task_info != NULL);
209 base_cpu = task_info->base_cpu;
a8ac85bb 210 }
9edcc12f
JB
211 }
212 else
213 {
214 /* We assume that the LWP of the PTID is equal to the CPU number. */
e38504b3 215 base_cpu = ptid.lwp ();
9edcc12f
JB
216 }
217
218 return base_cpu;
219}
220
989f3c58 221/* Given a ravenscar task (identified by its ptid_t PTID), return true
9edcc12f
JB
222 if this task is the currently active task on the cpu that task is
223 running on.
224
225 In other words, this function determine which CPU this task is
226 currently running on, and then return nonzero if the CPU in question
227 is executing the code for that task. If that's the case, then
228 that task's registers are in the CPU bank. Otherwise, the task
229 is currently suspended, and its registers have been saved in memory. */
230
0b790b1e
TT
231bool
232ravenscar_thread_target::task_is_currently_active (ptid_t ptid)
9edcc12f 233{
a8ac85bb 234 ptid_t active_task_ptid = active_task (get_thread_base_cpu (ptid));
9edcc12f 235
d7e15655 236 return ptid == active_task_ptid;
9edcc12f
JB
237}
238
239/* Return the CPU thread (as a ptid_t) on which the given ravenscar
240 task is running.
241
242 This is the thread that corresponds to the CPU on which the task
243 is running. */
244
a8ac85bb
TT
245ptid_t
246ravenscar_thread_target::get_base_thread_from_ravenscar_task (ptid_t ptid)
9edcc12f
JB
247{
248 int base_cpu;
249
250 if (!is_ravenscar_task (ptid))
251 return ptid;
252
a8ac85bb 253 base_cpu = get_thread_base_cpu (ptid);
e99b03dc 254 return ptid_t (ptid.pid (), base_cpu, 0);
9edcc12f
JB
255}
256
2da4b788
PA
257/* Fetch the ravenscar running thread from target memory, make sure
258 there's a corresponding thread in the thread list, and return it.
259 If the runtime is not initialized, return NULL. */
036b1ba8 260
2da4b788
PA
261thread_info *
262ravenscar_thread_target::add_active_thread ()
036b1ba8 263{
5b6d1e4f
PA
264 process_stratum_target *proc_target
265 = as_process_stratum_target (this->beneath ());
266
9edcc12f
JB
267 int base_cpu;
268
2da4b788 269 gdb_assert (!is_ravenscar_task (m_base_ptid));
a8ac85bb 270 base_cpu = get_thread_base_cpu (m_base_ptid);
9edcc12f 271
0b790b1e 272 if (!runtime_initialized ())
2da4b788 273 return nullptr;
036b1ba8 274
0b790b1e 275 /* Make sure we set m_base_ptid before calling active_task
036b1ba8 276 as the latter relies on it. */
2da4b788
PA
277 ptid_t active_ptid = active_task (base_cpu);
278 gdb_assert (active_ptid != null_ptid);
036b1ba8
JB
279
280 /* The running thread may not have been added to
e8032dde 281 system.tasking.debug's list yet; so ravenscar_update_thread_list
036b1ba8 282 may not always add it to the thread list. Add it here. */
2da4b788
PA
283 thread_info *active_thr = find_thread_ptid (proc_target, active_ptid);
284 if (active_thr == nullptr)
a8ac85bb
TT
285 {
286 active_thr = ::add_thread (proc_target, active_ptid);
287 m_cpu_map[active_ptid.tid ()] = base_cpu;
288 }
2da4b788 289 return active_thr;
036b1ba8
JB
290}
291
7f39f34a
JB
292/* The Ravenscar Runtime exports a symbol which contains the ID of
293 the thread that is currently running. Try to locate that symbol
294 and return its associated minimal symbol.
295 Return NULL if not found. */
296
3b7344d5 297static struct bound_minimal_symbol
989f3c58 298get_running_thread_msymbol ()
7f39f34a 299{
3b7344d5 300 struct bound_minimal_symbol msym;
7f39f34a
JB
301
302 msym = lookup_minimal_symbol (running_thread_name, NULL, NULL);
3b7344d5 303 if (!msym.minsym)
7f39f34a
JB
304 /* Older versions of the GNAT runtime were using a different
305 (less ideal) name for the symbol where the active thread ID
306 is stored. If we couldn't find the symbol using the latest
307 name, then try the old one. */
308 msym = lookup_minimal_symbol ("running_thread", NULL, NULL);
309
310 return msym;
311}
312
036b1ba8
JB
313/* Return True if the Ada Ravenscar run-time can be found in the
314 application. */
315
989f3c58
TT
316static bool
317has_ravenscar_runtime ()
036b1ba8 318{
6cbcc006
TT
319 struct bound_minimal_symbol msym_ravenscar_runtime_initializer
320 = lookup_minimal_symbol (ravenscar_runtime_initializer, NULL, NULL);
321 struct bound_minimal_symbol msym_known_tasks
322 = lookup_minimal_symbol (known_tasks_name, NULL, NULL);
323 struct bound_minimal_symbol msym_first_task
324 = lookup_minimal_symbol (first_task_name, NULL, NULL);
3b7344d5
TT
325 struct bound_minimal_symbol msym_running_thread
326 = get_running_thread_msymbol ();
036b1ba8 327
3b7344d5
TT
328 return (msym_ravenscar_runtime_initializer.minsym
329 && (msym_known_tasks.minsym || msym_first_task.minsym)
330 && msym_running_thread.minsym);
036b1ba8
JB
331}
332
333/* Return True if the Ada Ravenscar run-time can be found in the
334 application, and if it has been initialized on target. */
335
0b790b1e
TT
336bool
337ravenscar_thread_target::runtime_initialized ()
036b1ba8 338{
0b790b1e 339 return active_task (1) != null_ptid;
036b1ba8
JB
340}
341
7f39f34a
JB
342/* Return the ID of the thread that is currently running.
343 Return 0 if the ID could not be determined. */
036b1ba8
JB
344
345static CORE_ADDR
9edcc12f 346get_running_thread_id (int cpu)
036b1ba8 347{
3b7344d5 348 struct bound_minimal_symbol object_msym = get_running_thread_msymbol ();
036b1ba8
JB
349 int object_size;
350 int buf_size;
948f8e3d 351 gdb_byte *buf;
036b1ba8 352 CORE_ADDR object_addr;
6cbcc006
TT
353 struct type *builtin_type_void_data_ptr
354 = builtin_type (target_gdbarch ())->builtin_data_ptr;
036b1ba8 355
3b7344d5 356 if (!object_msym.minsym)
036b1ba8
JB
357 return 0;
358
036b1ba8 359 object_size = TYPE_LENGTH (builtin_type_void_data_ptr);
9edcc12f
JB
360 object_addr = (BMSYMBOL_VALUE_ADDRESS (object_msym)
361 + (cpu - 1) * object_size);
036b1ba8 362 buf_size = object_size;
224c3ddb 363 buf = (gdb_byte *) alloca (buf_size);
036b1ba8
JB
364 read_memory (object_addr, buf, buf_size);
365 return extract_typed_address (buf, builtin_type_void_data_ptr);
366}
367
f6ac5f3d 368void
6cbcc006
TT
369ravenscar_thread_target::resume (ptid_t ptid, int step,
370 enum gdb_signal siggnal)
036b1ba8 371{
485b851b
TT
372 /* If we see a wildcard resume, we simply pass that on. Otherwise,
373 arrange to resume the base ptid. */
0b790b1e 374 inferior_ptid = m_base_ptid;
39e2018a
TT
375 if (ptid.is_pid ())
376 {
377 /* We only have one process, so resume all threads of it. */
378 ptid = minus_one_ptid;
379 }
380 else if (ptid != minus_one_ptid)
485b851b
TT
381 ptid = m_base_ptid;
382 beneath ()->resume (ptid, step, siggnal);
036b1ba8
JB
383}
384
f6ac5f3d
PA
385ptid_t
386ravenscar_thread_target::wait (ptid_t ptid,
387 struct target_waitstatus *status,
b60cea74 388 target_wait_flags options)
036b1ba8 389{
5b6d1e4f
PA
390 process_stratum_target *beneath
391 = as_process_stratum_target (this->beneath ());
3b1b69bf 392 ptid_t event_ptid;
036b1ba8 393
485b851b
TT
394 if (ptid != minus_one_ptid)
395 ptid = m_base_ptid;
5b6d1e4f 396 event_ptid = beneath->wait (ptid, status, 0);
2da4b788
PA
397 /* Find any new threads that might have been created, and return the
398 active thread.
bed0c243
JB
399
400 Only do it if the program is still alive, though. Otherwise,
401 this causes problems when debugging through the remote protocol,
402 because we might try switching threads (and thus sending packets)
403 after the remote has disconnected. */
404 if (status->kind != TARGET_WAITKIND_EXITED
e9546579
TT
405 && status->kind != TARGET_WAITKIND_SIGNALLED
406 && runtime_initialized ())
bed0c243 407 {
2da4b788 408 m_base_ptid = event_ptid;
f6ac5f3d 409 this->update_thread_list ();
2da4b788 410 return this->add_active_thread ()->ptid;
bed0c243 411 }
550ab58d 412 return event_ptid;
036b1ba8
JB
413}
414
415/* Add the thread associated to the given TASK to the thread list
416 (if the thread has already been added, this is a no-op). */
417
2080266b
TT
418void
419ravenscar_thread_target::add_thread (struct ada_task_info *task)
036b1ba8 420{
5b6d1e4f 421 if (find_thread_ptid (current_inferior (), task->ptid) == NULL)
2080266b
TT
422 {
423 ::add_thread (current_inferior ()->process_target (), task->ptid);
424 m_cpu_map[task->ptid.tid ()] = task->base_cpu;
425 }
036b1ba8
JB
426}
427
f6ac5f3d
PA
428void
429ravenscar_thread_target::update_thread_list ()
036b1ba8 430{
0e29517d
TT
431 /* iterate_over_live_ada_tasks requires that inferior_ptid be set,
432 but this isn't always the case in target methods. So, we ensure
433 it here. */
434 scoped_restore save_ptid = make_scoped_restore (&inferior_ptid,
435 m_base_ptid);
436
036b1ba8
JB
437 /* Do not clear the thread list before adding the Ada task, to keep
438 the thread that the process stratum has included into it
0b790b1e 439 (m_base_ptid) and the running thread, that may not have been included
036b1ba8
JB
440 to system.tasking.debug's list yet. */
441
2080266b
TT
442 iterate_over_live_ada_tasks ([=] (struct ada_task_info *task)
443 {
444 this->add_thread (task);
445 });
036b1ba8
JB
446}
447
0b790b1e
TT
448ptid_t
449ravenscar_thread_target::active_task (int cpu)
036b1ba8 450{
9edcc12f 451 CORE_ADDR tid = get_running_thread_id (cpu);
036b1ba8
JB
452
453 if (tid == 0)
454 return null_ptid;
455 else
0b790b1e 456 return ptid_t (m_base_ptid.pid (), 0, tid);
036b1ba8
JB
457}
458
57810aa7 459bool
f6ac5f3d 460ravenscar_thread_target::thread_alive (ptid_t ptid)
036b1ba8
JB
461{
462 /* Ravenscar tasks are non-terminating. */
57810aa7 463 return true;
036b1ba8
JB
464}
465
a068643d 466std::string
f6ac5f3d 467ravenscar_thread_target::pid_to_str (ptid_t ptid)
036b1ba8 468{
d5d833af
TT
469 if (!is_ravenscar_task (ptid))
470 return beneath ()->pid_to_str (ptid);
471
472 return string_printf ("Ravenscar Thread %#x", (int) ptid.tid ());
036b1ba8
JB
473}
474
592f9bd7
TT
475/* Temporarily set the ptid of a regcache to some other value. When
476 this object is destroyed, the regcache's original ptid is
477 restored. */
478
479class temporarily_change_regcache_ptid
480{
481public:
482
483 temporarily_change_regcache_ptid (struct regcache *regcache, ptid_t new_ptid)
484 : m_regcache (regcache),
485 m_save_ptid (regcache->ptid ())
486 {
487 m_regcache->set_ptid (new_ptid);
488 }
489
490 ~temporarily_change_regcache_ptid ()
491 {
492 m_regcache->set_ptid (m_save_ptid);
493 }
494
495private:
496
497 /* The regcache. */
498 struct regcache *m_regcache;
499 /* The saved ptid. */
500 ptid_t m_save_ptid;
501};
502
f6ac5f3d
PA
503void
504ravenscar_thread_target::fetch_registers (struct regcache *regcache, int regnum)
036b1ba8 505{
222312d3 506 ptid_t ptid = regcache->ptid ();
036b1ba8 507
592f9bd7 508 if (runtime_initialized () && is_ravenscar_task (ptid))
7e35103a 509 {
592f9bd7
TT
510 if (task_is_currently_active (ptid))
511 {
512 ptid_t base = get_base_thread_from_ravenscar_task (ptid);
513 temporarily_change_regcache_ptid changer (regcache, base);
514 beneath ()->fetch_registers (regcache, regnum);
515 }
516 else
517 {
518 struct gdbarch *gdbarch = regcache->arch ();
519 struct ravenscar_arch_ops *arch_ops
520 = gdbarch_ravenscar_ops (gdbarch);
7e35103a 521
592f9bd7
TT
522 arch_ops->fetch_registers (regcache, regnum);
523 }
7e35103a 524 }
9edcc12f 525 else
d6ca69cd 526 beneath ()->fetch_registers (regcache, regnum);
036b1ba8
JB
527}
528
f6ac5f3d
PA
529void
530ravenscar_thread_target::store_registers (struct regcache *regcache,
531 int regnum)
036b1ba8 532{
222312d3 533 ptid_t ptid = regcache->ptid ();
036b1ba8 534
592f9bd7 535 if (runtime_initialized () && is_ravenscar_task (ptid))
7e35103a 536 {
592f9bd7
TT
537 if (task_is_currently_active (ptid))
538 {
539 ptid_t base = get_base_thread_from_ravenscar_task (ptid);
540 temporarily_change_regcache_ptid changer (regcache, base);
541 beneath ()->store_registers (regcache, regnum);
542 }
543 else
544 {
545 struct gdbarch *gdbarch = regcache->arch ();
546 struct ravenscar_arch_ops *arch_ops
547 = gdbarch_ravenscar_ops (gdbarch);
7e35103a 548
592f9bd7
TT
549 arch_ops->store_registers (regcache, regnum);
550 }
7e35103a 551 }
9edcc12f 552 else
d6ca69cd 553 beneath ()->store_registers (regcache, regnum);
036b1ba8
JB
554}
555
f6ac5f3d
PA
556void
557ravenscar_thread_target::prepare_to_store (struct regcache *regcache)
036b1ba8 558{
222312d3 559 ptid_t ptid = regcache->ptid ();
036b1ba8 560
592f9bd7 561 if (runtime_initialized () && is_ravenscar_task (ptid))
7e35103a 562 {
592f9bd7
TT
563 if (task_is_currently_active (ptid))
564 {
565 ptid_t base = get_base_thread_from_ravenscar_task (ptid);
566 temporarily_change_regcache_ptid changer (regcache, base);
567 beneath ()->prepare_to_store (regcache);
568 }
569 else
570 {
571 /* Nothing. */
572 }
7e35103a 573 }
9edcc12f 574 else
d6ca69cd 575 beneath ()->prepare_to_store (regcache);
036b1ba8
JB
576}
577
e02544b2
JB
578/* Implement the to_stopped_by_sw_breakpoint target_ops "method". */
579
57810aa7 580bool
f6ac5f3d 581ravenscar_thread_target::stopped_by_sw_breakpoint ()
e02544b2 582{
a52b3ae2
TT
583 scoped_restore_current_thread saver;
584 set_base_thread_from_ravenscar_task (inferior_ptid);
5b6ea500 585 return beneath ()->stopped_by_sw_breakpoint ();
e02544b2
JB
586}
587
588/* Implement the to_stopped_by_hw_breakpoint target_ops "method". */
589
57810aa7 590bool
f6ac5f3d 591ravenscar_thread_target::stopped_by_hw_breakpoint ()
e02544b2 592{
a52b3ae2
TT
593 scoped_restore_current_thread saver;
594 set_base_thread_from_ravenscar_task (inferior_ptid);
5b6ea500 595 return beneath ()->stopped_by_hw_breakpoint ();
e02544b2
JB
596}
597
598/* Implement the to_stopped_by_watchpoint target_ops "method". */
599
57810aa7 600bool
f6ac5f3d 601ravenscar_thread_target::stopped_by_watchpoint ()
e02544b2 602{
a52b3ae2
TT
603 scoped_restore_current_thread saver;
604 set_base_thread_from_ravenscar_task (inferior_ptid);
5b6ea500 605 return beneath ()->stopped_by_watchpoint ();
e02544b2
JB
606}
607
608/* Implement the to_stopped_data_address target_ops "method". */
609
57810aa7 610bool
f6ac5f3d 611ravenscar_thread_target::stopped_data_address (CORE_ADDR *addr_p)
e02544b2 612{
a52b3ae2
TT
613 scoped_restore_current_thread saver;
614 set_base_thread_from_ravenscar_task (inferior_ptid);
5b6ea500 615 return beneath ()->stopped_data_address (addr_p);
e02544b2
JB
616}
617
f6ac5f3d
PA
618void
619ravenscar_thread_target::mourn_inferior ()
036b1ba8 620{
0b790b1e 621 m_base_ptid = null_ptid;
fd9faca8 622 target_ops *beneath = this->beneath ();
fadf6add 623 current_inferior ()->unpush_target (this);
fd9faca8 624 beneath->mourn_inferior ();
036b1ba8
JB
625}
626
e02544b2
JB
627/* Implement the to_core_of_thread target_ops "method". */
628
f6ac5f3d
PA
629int
630ravenscar_thread_target::core_of_thread (ptid_t ptid)
e02544b2 631{
a52b3ae2
TT
632 scoped_restore_current_thread saver;
633 set_base_thread_from_ravenscar_task (inferior_ptid);
5b6ea500 634 return beneath ()->core_of_thread (inferior_ptid);
e02544b2
JB
635}
636
2080266b
TT
637/* Implement the target xfer_partial method. */
638
639enum target_xfer_status
640ravenscar_thread_target::xfer_partial (enum target_object object,
641 const char *annex,
642 gdb_byte *readbuf,
643 const gdb_byte *writebuf,
644 ULONGEST offset, ULONGEST len,
645 ULONGEST *xfered_len)
646{
647 scoped_restore save_ptid = make_scoped_restore (&inferior_ptid);
648 /* Calling get_base_thread_from_ravenscar_task can read memory from
649 the inferior. However, that function is written to prefer our
650 internal map, so it should not result in recursive calls in
651 practice. */
652 inferior_ptid = get_base_thread_from_ravenscar_task (inferior_ptid);
653 return beneath ()->xfer_partial (object, annex, readbuf, writebuf,
654 offset, len, xfered_len);
655}
656
036b1ba8
JB
657/* Observer on inferior_created: push ravenscar thread stratum if needed. */
658
659static void
a0ff652f 660ravenscar_inferior_created (inferior *inf)
036b1ba8 661{
cf3fbed4 662 const char *err_msg;
7e35103a
JB
663
664 if (!ravenscar_task_support
7dc7c195 665 || gdbarch_ravenscar_ops (target_gdbarch ()) == NULL
7e35103a 666 || !has_ravenscar_runtime ())
25abf4de
JB
667 return;
668
cf3fbed4
JB
669 err_msg = ada_get_tcb_types_info ();
670 if (err_msg != NULL)
671 {
8f6cb6c3 672 warning (_("%s. Task/thread support disabled."), err_msg);
cf3fbed4
JB
673 return;
674 }
675
3d4470e5 676 ravenscar_thread_target *rtarget = new ravenscar_thread_target ();
02980c56 677 inf->push_target (target_ops_up (rtarget));
3d4470e5
TT
678 thread_info *thr = rtarget->add_active_thread ();
679 if (thr != nullptr)
680 switch_to_thread (thr);
036b1ba8
JB
681}
682
f6ac5f3d
PA
683ptid_t
684ravenscar_thread_target::get_ada_task_ptid (long lwp, long thread)
036b1ba8 685{
0b790b1e 686 return ptid_t (m_base_ptid.pid (), 0, thread);
036b1ba8
JB
687}
688
036b1ba8
JB
689/* Command-list for the "set/show ravenscar" prefix command. */
690static struct cmd_list_element *set_ravenscar_list;
691static struct cmd_list_element *show_ravenscar_list;
692
036b1ba8
JB
693/* Implement the "show ravenscar task-switching" command. */
694
695static void
696show_ravenscar_task_switching_command (struct ui_file *file, int from_tty,
697 struct cmd_list_element *c,
698 const char *value)
699{
700 if (ravenscar_task_support)
701 fprintf_filtered (file, _("\
b64edec4 702Support for Ravenscar task/thread switching is enabled\n"));
036b1ba8
JB
703 else
704 fprintf_filtered (file, _("\
b64edec4 705Support for Ravenscar task/thread switching is disabled\n"));
036b1ba8
JB
706}
707
708/* Module startup initialization function, automagically called by
709 init.c. */
710
6c265988 711void _initialize_ravenscar ();
036b1ba8 712void
989f3c58 713_initialize_ravenscar ()
036b1ba8 714{
036b1ba8
JB
715 /* Notice when the inferior is created in order to push the
716 ravenscar ops if needed. */
c90e7d63
SM
717 gdb::observers::inferior_created.attach (ravenscar_inferior_created,
718 "ravenscar-thread");
036b1ba8 719
0743fc83
TT
720 add_basic_prefix_cmd ("ravenscar", no_class,
721 _("Prefix command for changing Ravenscar-specific settings."),
2f822da5 722 &set_ravenscar_list, 0, &setlist);
036b1ba8 723
0743fc83
TT
724 add_show_prefix_cmd ("ravenscar", no_class,
725 _("Prefix command for showing Ravenscar-specific settings."),
2f822da5 726 &show_ravenscar_list, 0, &showlist);
036b1ba8
JB
727
728 add_setshow_boolean_cmd ("task-switching", class_obscure,
dda83cd7 729 &ravenscar_task_support, _("\
590042fc
PW
730Enable or disable support for GNAT Ravenscar tasks."), _("\
731Show whether support for GNAT Ravenscar tasks is enabled."),
dda83cd7 732 _("\
036b1ba8
JB
733Enable or disable support for task/thread switching with the GNAT\n\
734Ravenscar run-time library for bareboard configuration."),
735 NULL, show_ravenscar_task_switching_command,
736 &set_ravenscar_list, &show_ravenscar_list);
737}
This page took 1.371429 seconds and 4 git commands to generate.