aboutsummaryrefslogtreecommitdiff
path: root/gdb/amd-dbgapi-target.c
diff options
context:
space:
mode:
Diffstat (limited to 'gdb/amd-dbgapi-target.c')
-rw-r--r--gdb/amd-dbgapi-target.c381
1 files changed, 295 insertions, 86 deletions
diff --git a/gdb/amd-dbgapi-target.c b/gdb/amd-dbgapi-target.c
index 073270f..a0210f4 100644
--- a/gdb/amd-dbgapi-target.c
+++ b/gdb/amd-dbgapi-target.c
@@ -1,6 +1,6 @@
/* Target used to communicate with the AMD Debugger API.
- Copyright (C) 2019-2024 Free Software Foundation, Inc.
+ Copyright (C) 2019-2025 Free Software Foundation, Inc.
This file is part of GDB.
@@ -24,6 +24,8 @@
#include "cli/cli-cmds.h"
#include "cli/cli-decode.h"
#include "cli/cli-style.h"
+#include "gdbcore.h"
+#include "gdbsupport/unordered_map.h"
#include "inf-loop.h"
#include "inferior.h"
#include "objfiles.h"
@@ -102,12 +104,26 @@ amd_dbgapi_lib_debug_module ()
static gdb::observers::token amd_dbgapi_target_inferior_created_observer_token;
+/* See amd-dbgapi-target.h. */
+
const gdb::observers::token &
get_amd_dbgapi_target_inferior_created_observer_token ()
{
return amd_dbgapi_target_inferior_created_observer_token;
}
+/* inferior_execd observer token. */
+
+static gdb::observers::token amd_dbgapi_target_inferior_execd_observer_token;
+
+/* See amd-dbgapi-target.h. */
+
+const gdb::observers::token &
+get_amd_dbgapi_target_inferior_execd_observer_token ()
+{
+ return amd_dbgapi_target_inferior_execd_observer_token;
+}
+
/* A type holding coordinates, etc. info for a given wave. */
struct wave_coordinates
@@ -207,13 +223,19 @@ struct amd_dbgapi_inferior_info
bool enabled = false;
} precise_memory;
- std::unordered_map<decltype (amd_dbgapi_breakpoint_id_t::handle),
+ gdb::unordered_map<decltype (amd_dbgapi_breakpoint_id_t::handle),
struct breakpoint *>
breakpoint_map;
/* List of pending events the amd-dbgapi target retrieved from the dbgapi. */
std::list<std::pair<ptid_t, target_waitstatus>> wave_events;
+ /* Map of threads with ongoing displaced steps to corresponding amd-dbgapi
+ displaced stepping handles. */
+ gdb::unordered_map<thread_info *,
+ decltype (amd_dbgapi_displaced_stepping_id_t::handle)>
+ stepping_id_map;
+
/* Map of wave ID to wave_info. We cache wave_info objects because
we need to access the info after the wave is gone, in the thread
exit nofication. E.g.:
@@ -221,12 +243,12 @@ struct amd_dbgapi_inferior_info
wave_info objects are added when we first see the wave, and
removed from a thread_deleted observer. */
- std::unordered_map<decltype (amd_dbgapi_wave_id_t::handle), wave_info>
+ gdb::unordered_map<decltype (amd_dbgapi_wave_id_t::handle), wave_info>
wave_info_map;
};
static amd_dbgapi_event_id_t process_event_queue
- (amd_dbgapi_process_id_t process_id,
+ (amd_dbgapi_inferior_info &info,
amd_dbgapi_event_kind_t until_event_kind = AMD_DBGAPI_EVENT_KIND_NONE);
static const target_info amd_dbgapi_target_info = {
@@ -290,6 +312,21 @@ struct amd_dbgapi_target final : public target_ops
bool stopped_by_sw_breakpoint () override;
bool stopped_by_hw_breakpoint () override;
+ bool supports_displaced_step (thread_info *thread) override
+ {
+ /* Handle displaced stepping for GPU threads only. */
+ if (!ptid_is_gpu (thread->ptid))
+ return beneath ()->supports_displaced_step (thread);
+
+ return true;
+ }
+
+ displaced_step_prepare_status displaced_step_prepare
+ (thread_info *thread, CORE_ADDR &displaced_pc) override;
+
+ displaced_step_finish_status displaced_step_finish
+ (thread_info *thread, const target_waitstatus &status) override;
+
private:
/* True if we must report thread events. */
bool m_report_thread_events = false;
@@ -420,6 +457,32 @@ async_event_handler_mark ()
mark_async_event_handler (amd_dbgapi_async_event_handler);
}
+/* Set forward progress requirement to REQUIRE for inferior INFO. */
+
+static void
+require_forward_progress (amd_dbgapi_inferior_info &info, bool require)
+{
+ /* If we try to disable forward progress requirement but the target expects
+ resumed threads to be committed to the target, we could wait for events
+ that will never arrive. */
+ if (!require)
+ gdb_assert (!info.inf->process_target ()->commit_resumed_state);
+
+ gdb_assert (info.process_id != AMD_DBGAPI_PROCESS_NONE);
+
+ /* Don't do unnecessary calls to amd-dbgapi to avoid polluting the logs. */
+ if (info.forward_progress_required == require)
+ return;
+
+ const auto progress
+ = require ? AMD_DBGAPI_PROGRESS_NORMAL : AMD_DBGAPI_PROGRESS_NO_FORWARD;
+ const auto status
+ = amd_dbgapi_process_set_progress (info.process_id, progress);
+ gdb_assert (status == AMD_DBGAPI_STATUS_SUCCESS);
+
+ info.forward_progress_required = require;
+}
+
/* Set forward progress requirement to REQUIRE for all processes of PROC_TARGET
matching PTID. */
@@ -434,21 +497,8 @@ require_forward_progress (ptid_t ptid, process_stratum_target *proc_target,
amd_dbgapi_inferior_info *info = get_amd_dbgapi_inferior_info (inf);
- if (info->process_id == AMD_DBGAPI_PROCESS_NONE)
- continue;
-
- /* Don't do unnecessary calls to amd-dbgapi to avoid polluting the logs. */
- if (info->forward_progress_required == require)
- continue;
-
- amd_dbgapi_status_t status
- = amd_dbgapi_process_set_progress
- (info->process_id, (require
- ? AMD_DBGAPI_PROGRESS_NORMAL
- : AMD_DBGAPI_PROGRESS_NO_FORWARD));
- gdb_assert (status == AMD_DBGAPI_STATUS_SUCCESS);
-
- info->forward_progress_required = require;
+ if (info->process_id != AMD_DBGAPI_PROCESS_NONE)
+ require_forward_progress (*info, require);
/* If ptid targets a single inferior and we have found it, no need to
continue. */
@@ -483,12 +533,12 @@ struct amd_dbgapi_target_breakpoint : public code_breakpoint
disposition = disp_donttouch;
}
- void re_set () override;
+ void re_set (program_space *) override;
void check_status (struct bpstat *bs) override;
};
void
-amd_dbgapi_target_breakpoint::re_set ()
+amd_dbgapi_target_breakpoint::re_set (program_space *)
{
/* Nothing. */
}
@@ -532,11 +582,12 @@ amd_dbgapi_target_breakpoint::check_status (struct bpstat *bs)
if (action == AMD_DBGAPI_BREAKPOINT_ACTION_RESUME)
return;
+ require_forward_progress (*info, false);
+
/* If the action is AMD_DBGAPI_BREAKPOINT_ACTION_HALT, we need to wait until
a breakpoint resume event for this breakpoint_id is seen. */
amd_dbgapi_event_id_t resume_event_id
- = process_event_queue (info->process_id,
- AMD_DBGAPI_EVENT_KIND_BREAKPOINT_RESUME);
+ = process_event_queue (*info, AMD_DBGAPI_EVENT_KIND_BREAKPOINT_RESUME);
/* We should always get a breakpoint_resume event after processing all
events generated by reporting the breakpoint hit. */
@@ -684,7 +735,7 @@ amd_dbgapi_target::resume (ptid_t scope_ptid, int step, enum gdb_signal signo)
switch (signo)
{
case GDB_SIGNAL_BUS:
- exception = AMD_DBGAPI_EXCEPTION_WAVE_APERTURE_VIOLATION;
+ exception = AMD_DBGAPI_EXCEPTION_WAVE_ADDRESS_ERROR;
break;
case GDB_SIGNAL_SEGV:
exception = AMD_DBGAPI_EXCEPTION_WAVE_MEMORY_VIOLATION;
@@ -1115,32 +1166,14 @@ add_gpu_thread (inferior *inf, ptid_t wave_ptid)
/* Process an event that was just pulled out of the amd-dbgapi library. */
static void
-process_one_event (amd_dbgapi_event_id_t event_id,
+process_one_event (amd_dbgapi_inferior_info &info,
+ amd_dbgapi_event_id_t event_id,
amd_dbgapi_event_kind_t event_kind)
{
/* Automatically mark this event processed when going out of scope. */
scoped_amd_dbgapi_event_processed mark_event_processed (event_id);
- amd_dbgapi_process_id_t process_id;
- amd_dbgapi_status_t status
- = amd_dbgapi_event_get_info (event_id, AMD_DBGAPI_EVENT_INFO_PROCESS,
- sizeof (process_id), &process_id);
- if (status != AMD_DBGAPI_STATUS_SUCCESS)
- error (_("event_get_info for event_%ld failed (%s)"), event_id.handle,
- get_status_string (status));
-
- amd_dbgapi_os_process_id_t pid;
- status = amd_dbgapi_process_get_info (process_id,
- AMD_DBGAPI_PROCESS_INFO_OS_ID,
- sizeof (pid), &pid);
- if (status != AMD_DBGAPI_STATUS_SUCCESS)
- error (_("process_get_info for process_%ld failed (%s)"),
- process_id.handle, get_status_string (status));
-
- auto *proc_target = current_inferior ()->process_target ();
- inferior *inf = find_inferior_pid (proc_target, pid);
- gdb_assert (inf != nullptr);
- amd_dbgapi_inferior_info *info = get_amd_dbgapi_inferior_info (inf);
+ gdb_assert (info.inf != nullptr);
switch (event_kind)
{
@@ -1148,14 +1181,14 @@ process_one_event (amd_dbgapi_event_id_t event_id,
case AMD_DBGAPI_EVENT_KIND_WAVE_STOP:
{
amd_dbgapi_wave_id_t wave_id;
- status
+ amd_dbgapi_status_t status
= amd_dbgapi_event_get_info (event_id, AMD_DBGAPI_EVENT_INFO_WAVE,
sizeof (wave_id), &wave_id);
if (status != AMD_DBGAPI_STATUS_SUCCESS)
error (_("event_get_info for event_%ld failed (%s)"),
event_id.handle, get_status_string (status));
- ptid_t event_ptid = make_gpu_ptid (pid, wave_id);
+ ptid_t event_ptid = make_gpu_ptid (info.inf->pid, wave_id);
target_waitstatus ws;
amd_dbgapi_wave_stop_reasons_t stop_reason;
@@ -1167,7 +1200,7 @@ process_one_event (amd_dbgapi_event_id_t event_id,
ws.set_thread_exited (0);
else if (status == AMD_DBGAPI_STATUS_SUCCESS)
{
- if (stop_reason & AMD_DBGAPI_WAVE_STOP_REASON_APERTURE_VIOLATION)
+ if (stop_reason & AMD_DBGAPI_WAVE_STOP_REASON_ADDRESS_ERROR)
ws.set_stopped (GDB_SIGNAL_BUS);
else if (stop_reason
& AMD_DBGAPI_WAVE_STOP_REASON_MEMORY_VIOLATION)
@@ -1196,9 +1229,10 @@ process_one_event (amd_dbgapi_event_id_t event_id,
else
ws.set_stopped (GDB_SIGNAL_0);
- thread_info *thread = proc_target->find_thread (event_ptid);
+ thread_info *thread
+ = info.inf->process_target ()->find_thread (event_ptid);
if (thread == nullptr)
- thread = add_gpu_thread (inf, event_ptid);
+ thread = add_gpu_thread (info.inf, event_ptid);
/* If the wave is stopped because of a software breakpoint, the
program counter needs to be adjusted so that it points to the
@@ -1220,7 +1254,7 @@ process_one_event (amd_dbgapi_event_id_t event_id,
error (_("wave_get_info for wave_%ld failed (%s)"),
wave_id.handle, get_status_string (status));
- info->wave_events.emplace_back (event_ptid, ws);
+ info.wave_events.emplace_back (event_ptid, ws);
break;
}
@@ -1238,7 +1272,7 @@ process_one_event (amd_dbgapi_event_id_t event_id,
When amd_dbgapi_target_breakpoint::check_status is called, the current
inferior is the inferior that hit the breakpoint, which should still be
the case now. */
- gdb_assert (inf == current_inferior ());
+ gdb_assert (info.inf == current_inferior ());
handle_solib_event ();
break;
@@ -1252,22 +1286,22 @@ process_one_event (amd_dbgapi_event_id_t event_id,
{
amd_dbgapi_runtime_state_t runtime_state;
- status = amd_dbgapi_event_get_info (event_id,
- AMD_DBGAPI_EVENT_INFO_RUNTIME_STATE,
- sizeof (runtime_state),
- &runtime_state);
+ amd_dbgapi_status_t status
+ = amd_dbgapi_event_get_info (event_id,
+ AMD_DBGAPI_EVENT_INFO_RUNTIME_STATE,
+ sizeof (runtime_state), &runtime_state);
if (status != AMD_DBGAPI_STATUS_SUCCESS)
error (_("event_get_info for event_%ld failed (%s)"),
event_id.handle, get_status_string (status));
gdb_assert (runtime_state == AMD_DBGAPI_RUNTIME_STATE_UNLOADED);
gdb_assert
- (info->runtime_state == AMD_DBGAPI_RUNTIME_STATE_LOADED_SUCCESS);
+ (info.runtime_state == AMD_DBGAPI_RUNTIME_STATE_LOADED_SUCCESS);
- info->runtime_state = runtime_state;
+ info.runtime_state = runtime_state;
- gdb_assert (inf->target_is_pushed (&the_amd_dbgapi_target));
- inf->unpush_target (&the_amd_dbgapi_target);
+ gdb_assert (info.inf->target_is_pushed (&the_amd_dbgapi_target));
+ info.inf->unpush_target (&the_amd_dbgapi_target);
}
break;
@@ -1308,20 +1342,18 @@ event_kind_str (amd_dbgapi_event_kind_t kind)
gdb_assert_not_reached ("unhandled amd_dbgapi_event_kind_t value");
}
-/* Drain the dbgapi event queue of a given process_id, or of all processes if
- process_id is AMD_DBGAPI_PROCESS_NONE. Stop processing the events if an
- event of a given kind is requested and `process_id` is not
- AMD_DBGAPI_PROCESS_NONE. Wave stop events that are not returned are queued
- into their inferior's amd_dbgapi_inferior_info pending wave events. */
+/* Drain the dbgapi event queue of a given inferior. Stop processing the
+ events if an event of a given kind is requested (not AMD_DBGAPI_EVENT_NONE).
+ Wave stop events that are not returned are queued into their inferior's
+ amd_dbgapi_inferior_info pending wave events. */
static amd_dbgapi_event_id_t
-process_event_queue (amd_dbgapi_process_id_t process_id,
+process_event_queue (amd_dbgapi_inferior_info &info,
amd_dbgapi_event_kind_t until_event_kind)
{
- /* An event of a given type can only be requested from a single
- process_id. */
- gdb_assert (until_event_kind == AMD_DBGAPI_EVENT_KIND_NONE
- || process_id != AMD_DBGAPI_PROCESS_NONE);
+ /* Pulling events with forward progress required may result in bad
+ performance, make sure it is not required. */
+ gdb_assert (!info.forward_progress_required);
while (true)
{
@@ -1329,7 +1361,7 @@ process_event_queue (amd_dbgapi_process_id_t process_id,
amd_dbgapi_event_kind_t event_kind;
amd_dbgapi_status_t status
- = amd_dbgapi_process_next_pending_event (process_id, &event_id,
+ = amd_dbgapi_process_next_pending_event (info.process_id, &event_id,
&event_kind);
if (status != AMD_DBGAPI_STATUS_SUCCESS)
@@ -1345,7 +1377,7 @@ process_event_queue (amd_dbgapi_process_id_t process_id,
if (event_id == AMD_DBGAPI_EVENT_NONE || event_kind == until_event_kind)
return event_id;
- process_one_event (event_id, event_kind);
+ process_one_event (info, event_id, event_kind);
}
}
@@ -1450,7 +1482,7 @@ amd_dbgapi_target::wait (ptid_t ptid, struct target_waitstatus *ws,
/* Drain the events for the current inferior from the amd_dbgapi and
preserve the ordering. */
auto info = get_amd_dbgapi_inferior_info (current_inferior ());
- process_event_queue (info->process_id, AMD_DBGAPI_EVENT_KIND_NONE);
+ process_event_queue (*info);
std::tie (event_ptid, gpu_waitstatus) = consume_one_event (ptid.pid ());
if (event_ptid == minus_one_ptid)
@@ -1837,13 +1869,14 @@ amd_dbgapi_target::update_thread_list ()
if (changed == AMD_DBGAPI_CHANGED_NO)
continue;
+ gdb::unique_xmalloc_ptr<amd_dbgapi_wave_id_t> wave_list_holder
+ (wave_list);
+
/* Create a set and free the wave list. */
std::set<ptid_t::tid_type> threads;
for (size_t i = 0; i < count; ++i)
threads.emplace (wave_list[i].handle);
- xfree (wave_list);
-
/* Prune the wave_ids that already have a thread_info. Any thread_info
which does not have a corresponding wave_id represents a wave which
is gone at this point and should be deleted. */
@@ -1896,6 +1929,122 @@ amd_dbgapi_target::update_thread_list ()
this->beneath ()->update_thread_list ();
}
+displaced_step_prepare_status
+amd_dbgapi_target::displaced_step_prepare (thread_info *thread,
+ CORE_ADDR &displaced_pc)
+{
+ if (!ptid_is_gpu (thread->ptid))
+ return beneath ()->displaced_step_prepare (thread, displaced_pc);
+
+ gdb_assert (!thread->displaced_step_state.in_progress ());
+
+ /* Read the bytes that were overwritten by the breakpoint instruction being
+ stepped over. */
+ CORE_ADDR original_pc = regcache_read_pc (get_thread_regcache (thread));
+ gdbarch *arch = get_thread_regcache (thread)->arch ();
+ size_t size = get_amdgpu_gdbarch_tdep (arch)->breakpoint_instruction_size;
+ gdb::byte_vector overwritten_bytes (size);
+
+ read_memory (original_pc, overwritten_bytes.data (), size);
+
+ /* Ask dbgapi to start the displaced step. */
+ amd_dbgapi_wave_id_t wave_id = get_amd_dbgapi_wave_id (thread->ptid);
+ amd_dbgapi_displaced_stepping_id_t stepping_id;
+ amd_dbgapi_status_t status
+ = amd_dbgapi_displaced_stepping_start (wave_id, overwritten_bytes.data (),
+ &stepping_id);
+
+ switch (status)
+ {
+ case AMD_DBGAPI_STATUS_SUCCESS:
+ break;
+
+ case AMD_DBGAPI_STATUS_ERROR_DISPLACED_STEPPING_BUFFER_NOT_AVAILABLE:
+ return DISPLACED_STEP_PREPARE_STATUS_UNAVAILABLE;
+
+ case AMD_DBGAPI_STATUS_ERROR_ILLEGAL_INSTRUCTION:
+ return DISPLACED_STEP_PREPARE_STATUS_CANT;
+
+ default:
+ error (_("amd_dbgapi_displaced_stepping_start failed (%s)"),
+ get_status_string (status));
+ }
+
+ /* Save the displaced stepping id in the per-inferior info. */
+ amd_dbgapi_inferior_info *info = get_amd_dbgapi_inferior_info (thread->inf);
+
+ bool inserted
+ = info->stepping_id_map.emplace (thread, stepping_id.handle).second;
+ gdb_assert (inserted);
+
+ /* Get the new (displaced) PC. */
+ status = amd_dbgapi_wave_get_info (wave_id, AMD_DBGAPI_WAVE_INFO_PC,
+ sizeof (displaced_pc), &displaced_pc);
+ if (status != AMD_DBGAPI_STATUS_SUCCESS)
+ {
+ amd_dbgapi_displaced_stepping_complete (wave_id, stepping_id);
+ error (_("amd_dbgapi_wave_get_info failed (%s), could not get the "
+ "thread's displaced PC."),
+ get_status_string (status));
+ }
+
+ displaced_debug_printf ("selected buffer at %#lx", displaced_pc);
+
+ /* We may have written some registers, so flush the register cache. */
+ registers_changed_thread (thread);
+
+ return DISPLACED_STEP_PREPARE_STATUS_OK;
+}
+
+displaced_step_finish_status
+amd_dbgapi_target::displaced_step_finish (thread_info *thread,
+ const target_waitstatus &ws)
+{
+ if (!ptid_is_gpu (thread->ptid))
+ return beneath ()->displaced_step_finish (thread, ws);
+
+ gdb_assert (thread->displaced_step_state.in_progress ());
+
+ /* Find the displaced stepping id for this thread. */
+ amd_dbgapi_inferior_info *info = get_amd_dbgapi_inferior_info (thread->inf);
+ auto entry = info->stepping_id_map.extract (thread);
+
+ gdb_assert (entry.has_value ());
+ amd_dbgapi_displaced_stepping_id_t stepping_id {entry->second};
+
+ /* If the thread exited while stepping, we are done. The code above
+ cleared our associated resources. We don't want to call dbgapi
+ below: since the thread is gone, we wouldn't be able to find the
+ necessary wave ID. dbgapi already took care of releasing its
+ displaced-stepping-related resources when it deleted the
+ wave. */
+ if (ws.kind () == TARGET_WAITKIND_THREAD_EXITED)
+ return DISPLACED_STEP_FINISH_STATUS_OK;
+
+ amd_dbgapi_wave_id_t wave_id = get_amd_dbgapi_wave_id (thread->ptid);
+ amd_dbgapi_wave_stop_reasons_t stop_reason;
+ amd_dbgapi_status_t status
+ = amd_dbgapi_wave_get_info (wave_id, AMD_DBGAPI_WAVE_INFO_STOP_REASON,
+ sizeof (stop_reason), &stop_reason);
+
+ if (status != AMD_DBGAPI_STATUS_SUCCESS)
+ error (_("wave_get_info for wave_%ld failed (%s)"), wave_id.handle,
+ get_status_string (status));
+
+ status = amd_dbgapi_displaced_stepping_complete (wave_id, stepping_id);
+
+ if (status != AMD_DBGAPI_STATUS_SUCCESS)
+ error (_("amd_dbgapi_displaced_stepping_complete failed (%s)"),
+ get_status_string (status));
+
+ /* We may have written some registers, so flush the register cache. */
+ registers_changed_thread (thread);
+
+ return (stop_reason & AMD_DBGAPI_WAVE_STOP_REASON_SINGLE_STEP) != 0
+ ? DISPLACED_STEP_FINISH_STATUS_OK
+ : DISPLACED_STEP_FINISH_STATUS_NOT_EXECUTED;
+}
+
/* inferior_created observer. */
static void
@@ -1992,19 +2141,35 @@ amd_dbgapi_inferior_pre_detach (inferior *inf)
detach_amd_dbgapi (inf);
}
-/* get_os_pid callback. */
+/* client_process_get_info callback. */
static amd_dbgapi_status_t
-amd_dbgapi_get_os_pid_callback
- (amd_dbgapi_client_process_id_t client_process_id, pid_t *pid)
+amd_dbgapi_client_process_get_info_callback
+ (amd_dbgapi_client_process_id_t client_process_id,
+ amd_dbgapi_client_process_info_t query, size_t value_size, void *value)
{
inferior *inf = reinterpret_cast<inferior *> (client_process_id);
if (inf->pid == 0)
return AMD_DBGAPI_STATUS_ERROR_PROCESS_EXITED;
- *pid = inf->pid;
- return AMD_DBGAPI_STATUS_SUCCESS;
+ if (value == nullptr)
+ return AMD_DBGAPI_STATUS_ERROR_INVALID_ARGUMENT;
+
+ switch (query)
+ {
+ case AMD_DBGAPI_CLIENT_PROCESS_INFO_OS_PID:
+ if (value_size != sizeof (amd_dbgapi_os_process_id_t))
+ return AMD_DBGAPI_STATUS_ERROR_INVALID_ARGUMENT_COMPATIBILITY;
+
+ *static_cast<amd_dbgapi_os_process_id_t *> (value) = inf->pid;
+ return AMD_DBGAPI_STATUS_SUCCESS;
+
+ case AMD_DBGAPI_CLIENT_PROCESS_INFO_CORE_STATE:
+ return AMD_DBGAPI_STATUS_ERROR_NOT_AVAILABLE;
+ }
+
+ return AMD_DBGAPI_STATUS_ERROR_INVALID_ARGUMENT;
}
/* insert_breakpoint callback. */
@@ -2060,6 +2225,50 @@ amd_dbgapi_remove_breakpoint_callback
return AMD_DBGAPI_STATUS_SUCCESS;
}
+/* xfer_global_memory callback. */
+
+static amd_dbgapi_status_t
+amd_dbgapi_xfer_global_memory_callback
+ (amd_dbgapi_client_process_id_t client_process_id,
+ amd_dbgapi_global_address_t global_address,
+ amd_dbgapi_size_t *value_size, void *read_buffer,
+ const void *write_buffer)
+{
+ if ((read_buffer != nullptr) == (write_buffer != nullptr))
+ return AMD_DBGAPI_STATUS_ERROR_INVALID_ARGUMENT_COMPATIBILITY;
+
+ inferior *inf = reinterpret_cast<inferior *> (client_process_id);
+
+ /* We need to set inferior_ptid / current_inferior as those are
+ used by the target which will process the xfer_partial request.
+
+ Note that we end up here when amd-dbgapi tries to access device memory or
+ register content which are at this point mapped/saved in the host process
+ memory. As a consequence, unwinding GPU frames will most likely call into
+ here. If we used switch_to_thread to select a host thread, this would
+ implicitly call reinit_frame_cache. We do not want to clear the frame
+ cache while trying to build it. */
+ scoped_restore save_inferior_ptid = make_scoped_restore (&inferior_ptid);
+ scoped_restore_current_inferior restore_current_inferior;
+ scoped_restore_current_program_space restore_program_space;
+ inferior_ptid = ptid_t (inf->pid);
+ set_current_inferior (inf);
+ set_current_program_space (inf->pspace);
+
+ target_xfer_status status
+ = target_xfer_partial (inf->top_target (), TARGET_OBJECT_RAW_MEMORY,
+ nullptr, static_cast<gdb_byte *> (read_buffer),
+ static_cast<const gdb_byte *> (write_buffer),
+ global_address, *value_size, value_size);
+
+ if (status == TARGET_XFER_EOF)
+ return AMD_DBGAPI_STATUS_ERROR_PROCESS_EXITED;
+ else if (status != TARGET_XFER_OK)
+ return AMD_DBGAPI_STATUS_ERROR_MEMORY_ACCESS;
+
+ return AMD_DBGAPI_STATUS_SUCCESS;
+}
+
/* signal_received observer. */
static void
@@ -2138,9 +2347,10 @@ amd_dbgapi_log_message_callback (amd_dbgapi_log_level_t level,
static amd_dbgapi_callbacks_t dbgapi_callbacks = {
.allocate_memory = malloc,
.deallocate_memory = free,
- .get_os_pid = amd_dbgapi_get_os_pid_callback,
+ .client_process_get_info = amd_dbgapi_client_process_get_info_callback,
.insert_breakpoint = amd_dbgapi_insert_breakpoint_callback,
.remove_breakpoint = amd_dbgapi_remove_breakpoint_callback,
+ .xfer_global_memory = amd_dbgapi_xfer_global_memory_callback,
.log_message = amd_dbgapi_log_message_callback,
};
@@ -2279,10 +2489,7 @@ maybe_reset_amd_dbgapi ()
get_status_string (status));
}
-extern initialize_file_ftype _initialize_amd_dbgapi_target;
-
-void
-_initialize_amd_dbgapi_target ()
+INIT_GDB_FILE (amd_dbgapi_target)
{
/* Make sure the loaded debugger library version is greater than or equal to
the one used to build GDB. */
@@ -2310,7 +2517,9 @@ _initialize_amd_dbgapi_target ()
gdb::observers::inferior_created.attach
(amd_dbgapi_target_inferior_created,
amd_dbgapi_target_inferior_created_observer_token, "amd-dbgapi");
- gdb::observers::inferior_execd.attach (amd_dbgapi_inferior_execd, "amd-dbgapi");
+ gdb::observers::inferior_execd.attach
+ (amd_dbgapi_inferior_execd, amd_dbgapi_target_inferior_execd_observer_token,
+ "amd-dbgapi");
gdb::observers::inferior_forked.attach (amd_dbgapi_inferior_forked, "amd-dbgapi");
gdb::observers::inferior_exit.attach (amd_dbgapi_inferior_exited, "amd-dbgapi");
gdb::observers::inferior_pre_detach.attach (amd_dbgapi_inferior_pre_detach, "amd-dbgapi");