mirror of
https://github.com/bminor/binutils-gdb.git
synced 2025-11-16 12:34:43 +00:00
Compare commits
5 Commits
gdb-11-bra
...
users/sima
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fe0e47ac81 | ||
|
|
5672720dd1 | ||
|
|
2dd1cd011c | ||
|
|
7e17ef8ca4 | ||
|
|
5c879edf04 |
@@ -41,6 +41,7 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <forward_list>
|
||||
#include <set>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
|
||||
78
gdb/infrun.c
78
gdb/infrun.c
@@ -67,6 +67,9 @@
|
||||
#include "gdbsupport/gdb_select.h"
|
||||
#include <unordered_map>
|
||||
#include "async-event.h"
|
||||
#include "gdbsupport/selftest.h"
|
||||
#include "scoped-mock-context.h"
|
||||
#include "test-target.h"
|
||||
|
||||
/* Prototypes for local functions */
|
||||
|
||||
@@ -2068,9 +2071,11 @@ start_step_over (void)
|
||||
/* Update global variables holding ptids to hold NEW_PTID if they were
|
||||
holding OLD_PTID. */
|
||||
static void
|
||||
infrun_thread_ptid_changed (ptid_t old_ptid, ptid_t new_ptid)
|
||||
infrun_thread_ptid_changed (process_stratum_target *target,
|
||||
ptid_t old_ptid, ptid_t new_ptid)
|
||||
{
|
||||
if (inferior_ptid == old_ptid)
|
||||
if (inferior_ptid == old_ptid
|
||||
&& current_inferior ()->process_target () == target)
|
||||
inferior_ptid = new_ptid;
|
||||
}
|
||||
|
||||
@@ -9455,6 +9460,70 @@ infrun_async_inferior_event_handler (gdb_client_data data)
|
||||
inferior_event_handler (INF_REG_EVENT);
|
||||
}
|
||||
|
||||
namespace selftests
|
||||
{
|
||||
|
||||
/* Verify that when two threads with the same ptid exist (from two different
|
||||
targets) and one of them changes ptid, we only update inferior_ptid if
|
||||
it is appropriate. */
|
||||
|
||||
static void
|
||||
infrun_thread_ptid_changed ()
|
||||
{
|
||||
gdbarch *arch = current_inferior ()->gdbarch;
|
||||
|
||||
/* The thread which inferior_ptid represents changes ptid. */
|
||||
{
|
||||
scoped_restore_current_pspace_and_thread restore;
|
||||
|
||||
scoped_mock_context<test_target_ops> target1 (arch);
|
||||
scoped_mock_context<test_target_ops> target2 (arch);
|
||||
target2.mock_inferior.next = &target1.mock_inferior;
|
||||
|
||||
ptid_t old_ptid (111, 222);
|
||||
ptid_t new_ptid (111, 333);
|
||||
|
||||
target1.mock_inferior.pid = old_ptid.pid ();
|
||||
target1.mock_thread.ptid = old_ptid;
|
||||
target2.mock_inferior.pid = old_ptid.pid ();
|
||||
target2.mock_thread.ptid = old_ptid;
|
||||
|
||||
auto restore_inferior_ptid = make_scoped_restore (&inferior_ptid, old_ptid);
|
||||
set_current_inferior (&target1.mock_inferior);
|
||||
|
||||
thread_change_ptid (&target1.mock_target, old_ptid, new_ptid);
|
||||
|
||||
gdb_assert (inferior_ptid == new_ptid);
|
||||
}
|
||||
|
||||
/* A thread with the same ptid as inferior_ptid, but from another target,
|
||||
changes ptid. */
|
||||
{
|
||||
scoped_restore_current_pspace_and_thread restore;
|
||||
|
||||
scoped_mock_context<test_target_ops> target1 (arch);
|
||||
scoped_mock_context<test_target_ops> target2 (arch);
|
||||
target2.mock_inferior.next = &target1.mock_inferior;
|
||||
|
||||
ptid_t old_ptid (111, 222);
|
||||
ptid_t new_ptid (111, 333);
|
||||
|
||||
target1.mock_inferior.pid = old_ptid.pid ();
|
||||
target1.mock_thread.ptid = old_ptid;
|
||||
target2.mock_inferior.pid = old_ptid.pid ();
|
||||
target2.mock_thread.ptid = old_ptid;
|
||||
|
||||
auto restore_inferior_ptid = make_scoped_restore (&inferior_ptid, old_ptid);
|
||||
set_current_inferior (&target2.mock_inferior);
|
||||
|
||||
thread_change_ptid (&target1.mock_target, old_ptid, new_ptid);
|
||||
|
||||
gdb_assert (inferior_ptid == old_ptid);
|
||||
}
|
||||
}
|
||||
|
||||
} /* namespace selftests */
|
||||
|
||||
void _initialize_infrun ();
|
||||
void
|
||||
_initialize_infrun ()
|
||||
@@ -9756,4 +9825,9 @@ or signalled."),
|
||||
show_observer_mode,
|
||||
&setlist,
|
||||
&showlist);
|
||||
|
||||
#if GDB_SELF_TEST
|
||||
selftests::register_test ("infrun_thread_ptid_changed",
|
||||
selftests::infrun_thread_ptid_changed);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ struct so_list;
|
||||
struct objfile;
|
||||
struct thread_info;
|
||||
struct inferior;
|
||||
struct process_stratum_target;
|
||||
struct trace_state_variable;
|
||||
|
||||
namespace gdb
|
||||
@@ -165,8 +166,9 @@ extern observable<struct gdbarch */* newarch */> architecture_changed;
|
||||
|
||||
/* The thread's ptid has changed. The OLD_PTID parameter specifies
|
||||
the old value, and NEW_PTID specifies the new value. */
|
||||
extern observable<ptid_t /* old_ptid */, ptid_t /* new_ptid */>
|
||||
thread_ptid_changed;
|
||||
extern observable<process_stratum_target * /* target */,
|
||||
ptid_t /* old_ptid */, ptid_t /* new_ptid */>
|
||||
thread_ptid_changed;
|
||||
|
||||
/* The inferior INF has been added to the list of inferiors. At
|
||||
this point, it might not be associated with any process. */
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
#include "gdbarch.h"
|
||||
#include "cli/cli-style.h"
|
||||
#include "async-event.h"
|
||||
#include <forward_list>
|
||||
|
||||
static const target_info record_btrace_target_info = {
|
||||
"record-btrace",
|
||||
|
||||
228
gdb/regcache.c
228
gdb/regcache.c
@@ -29,7 +29,7 @@
|
||||
#include "reggroups.h"
|
||||
#include "observable.h"
|
||||
#include "regset.h"
|
||||
#include <forward_list>
|
||||
#include <unordered_map>
|
||||
|
||||
/*
|
||||
* DATA STRUCTURE
|
||||
@@ -313,31 +313,48 @@ reg_buffer::assert_regnum (int regnum) const
|
||||
gdb_assert (regnum < gdbarch_num_regs (arch ()));
|
||||
}
|
||||
|
||||
/* Global structure containing the current regcache. */
|
||||
/* Type to map a ptid to a list of regcaches (one thread may have multiple
|
||||
regcaches, associated to different gdbarches). */
|
||||
|
||||
using ptid_regcache_map
|
||||
= std::unordered_multimap<ptid_t, regcache_up, hash_ptid>;
|
||||
|
||||
/* Type to map a target to a ptid_regcache_map, holding the regcaches for the
|
||||
threads defined by that target. */
|
||||
|
||||
using target_ptid_regcache_map
|
||||
= std::unordered_map<process_stratum_target *, ptid_regcache_map>;
|
||||
|
||||
/* Global structure containing the existing regcaches. */
|
||||
|
||||
/* NOTE: this is a write-through cache. There is no "dirty" bit for
|
||||
recording if the register values have been changed (eg. by the
|
||||
user). Therefore all registers must be written back to the
|
||||
target when appropriate. */
|
||||
std::forward_list<regcache *> regcache::current_regcache;
|
||||
static target_ptid_regcache_map regcaches;
|
||||
|
||||
struct regcache *
|
||||
get_thread_arch_aspace_regcache (process_stratum_target *target,
|
||||
ptid_t ptid, struct gdbarch *gdbarch,
|
||||
ptid_t ptid, gdbarch *arch,
|
||||
struct address_space *aspace)
|
||||
{
|
||||
gdb_assert (target != nullptr);
|
||||
|
||||
for (const auto ®cache : regcache::current_regcache)
|
||||
if (regcache->target () == target
|
||||
&& regcache->ptid () == ptid
|
||||
&& regcache->arch () == gdbarch)
|
||||
return regcache;
|
||||
/* Find the ptid -> regcache map for this target. */
|
||||
auto &ptid_regc_map = regcaches[target];
|
||||
|
||||
regcache *new_regcache = new regcache (target, gdbarch, aspace);
|
||||
/* Check first if a regcache for this arch already exists. */
|
||||
auto range = ptid_regc_map.equal_range (ptid);
|
||||
for (auto it = range.first; it != range.second; it++)
|
||||
{
|
||||
if (it->second->arch () == arch)
|
||||
return it->second.get ();
|
||||
}
|
||||
|
||||
regcache::current_regcache.push_front (new_regcache);
|
||||
/* It does not exist, create it. */
|
||||
regcache *new_regcache (new regcache (target, arch, aspace));
|
||||
new_regcache->set_ptid (ptid);
|
||||
ptid_regc_map.insert (std::make_pair (ptid, new_regcache));
|
||||
|
||||
return new_regcache;
|
||||
}
|
||||
@@ -412,15 +429,27 @@ regcache_observer_target_changed (struct target_ops *target)
|
||||
registers_changed ();
|
||||
}
|
||||
|
||||
/* Update global variables old ptids to hold NEW_PTID if they were
|
||||
holding OLD_PTID. */
|
||||
void
|
||||
regcache::regcache_thread_ptid_changed (ptid_t old_ptid, ptid_t new_ptid)
|
||||
/* Update regcaches related to OLD_PTID to now use NEW_PTID. */
|
||||
static void
|
||||
regcache_thread_ptid_changed (process_stratum_target *target,
|
||||
ptid_t old_ptid, ptid_t new_ptid)
|
||||
{
|
||||
for (auto ®cache : regcache::current_regcache)
|
||||
auto ptid_regc_map_it = regcaches.find (target);
|
||||
|
||||
if (ptid_regc_map_it == regcaches.end ())
|
||||
return;
|
||||
|
||||
auto &ptid_regc_map = ptid_regc_map_it->second;
|
||||
auto range = ptid_regc_map.equal_range (old_ptid);
|
||||
for (auto it = range.first; it != range.second;)
|
||||
{
|
||||
if (regcache->ptid () == old_ptid)
|
||||
regcache->set_ptid (new_ptid);
|
||||
regcache_up rc = std::move (it->second);
|
||||
rc->set_ptid (new_ptid);
|
||||
|
||||
/* Remove old before inserting new, to avoid rehashing,
|
||||
which would invalidate iterators. */
|
||||
it = ptid_regc_map.erase (it);
|
||||
ptid_regc_map.insert (std::make_pair (new_ptid, std::move (rc)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -438,20 +467,37 @@ regcache::regcache_thread_ptid_changed (ptid_t old_ptid, ptid_t new_ptid)
|
||||
void
|
||||
registers_changed_ptid (process_stratum_target *target, ptid_t ptid)
|
||||
{
|
||||
for (auto oit = regcache::current_regcache.before_begin (),
|
||||
it = std::next (oit);
|
||||
it != regcache::current_regcache.end ();
|
||||
)
|
||||
if (target == nullptr)
|
||||
{
|
||||
struct regcache *regcache = *it;
|
||||
if ((target == nullptr || regcache->target () == target)
|
||||
&& regcache->ptid ().matches (ptid))
|
||||
/* Since there can be ptid clashes between targets, it's not valid to
|
||||
pass a ptid without saying to which target it belongs. */
|
||||
gdb_assert (ptid == minus_one_ptid);
|
||||
|
||||
/* Delete all the regcaches. */
|
||||
for (auto &pair : regcaches)
|
||||
pair.second.clear ();
|
||||
}
|
||||
else if (ptid != minus_one_ptid)
|
||||
{
|
||||
/* Non-NULL target and non-minus_one_ptid, delete all regcaches belonging
|
||||
to this (TARGET, PTID). */
|
||||
auto ptid_regc_map_it = regcaches.find (target);
|
||||
if (ptid_regc_map_it != regcaches.end ())
|
||||
{
|
||||
delete regcache;
|
||||
it = regcache::current_regcache.erase_after (oit);
|
||||
auto &ptid_regc_map = ptid_regc_map_it->second;
|
||||
ptid_regc_map.erase (ptid);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Non-NULL target and minus_one_ptid, delete all regcaches
|
||||
associated to this target. */
|
||||
auto ptid_regc_map_it = regcaches.find (target);
|
||||
if (ptid_regc_map_it != regcaches.end ())
|
||||
{
|
||||
auto &ptid_regc_map = ptid_regc_map_it->second;
|
||||
ptid_regc_map.clear ();
|
||||
}
|
||||
else
|
||||
oit = it++;
|
||||
}
|
||||
|
||||
if ((target == nullptr || current_thread_target == target)
|
||||
@@ -1433,19 +1479,17 @@ register_dump::dump (ui_file *file)
|
||||
|
||||
namespace selftests {
|
||||
|
||||
class regcache_access : public regcache
|
||||
static size_t
|
||||
regcaches_size ()
|
||||
{
|
||||
public:
|
||||
|
||||
/* Return the number of elements in current_regcache. */
|
||||
|
||||
static size_t
|
||||
current_regcache_size ()
|
||||
{
|
||||
return std::distance (regcache::current_regcache.begin (),
|
||||
regcache::current_regcache.end ());
|
||||
}
|
||||
};
|
||||
size_t size = 0;
|
||||
for (auto it = regcaches.begin (); it != regcaches.end (); ++it)
|
||||
{
|
||||
auto &ptid_regc_map = it->second;
|
||||
size += ptid_regc_map.size ();
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
/* Wrapper around get_thread_arch_aspace_regcache that does some self checks. */
|
||||
|
||||
@@ -1463,10 +1507,10 @@ test_get_thread_arch_aspace_regcache (process_stratum_target *target,
|
||||
}
|
||||
|
||||
static void
|
||||
current_regcache_test (void)
|
||||
regcaches_test (void)
|
||||
{
|
||||
/* It is empty at the start. */
|
||||
SELF_CHECK (regcache_access::current_regcache_size () == 0);
|
||||
SELF_CHECK (regcaches_size () == 0);
|
||||
|
||||
ptid_t ptid1 (1), ptid2 (2), ptid3 (3);
|
||||
|
||||
@@ -1474,57 +1518,56 @@ current_regcache_test (void)
|
||||
test_target_ops test_target2;
|
||||
|
||||
/* Get regcache from (target1,ptid1), a new regcache is added to
|
||||
current_regcache. */
|
||||
REGCACHES. */
|
||||
test_get_thread_arch_aspace_regcache (&test_target1, ptid1,
|
||||
target_gdbarch (),
|
||||
NULL);
|
||||
SELF_CHECK (regcache_access::current_regcache_size () == 1);
|
||||
SELF_CHECK (regcaches_size () == 1);
|
||||
|
||||
/* Get regcache from (target1,ptid2), a new regcache is added to
|
||||
current_regcache. */
|
||||
REGCACHES. */
|
||||
test_get_thread_arch_aspace_regcache (&test_target1, ptid2,
|
||||
target_gdbarch (),
|
||||
NULL);
|
||||
SELF_CHECK (regcache_access::current_regcache_size () == 2);
|
||||
SELF_CHECK (regcaches_size () == 2);
|
||||
|
||||
/* Get regcache from (target1,ptid3), a new regcache is added to
|
||||
current_regcache. */
|
||||
REGCACHES. */
|
||||
test_get_thread_arch_aspace_regcache (&test_target1, ptid3,
|
||||
target_gdbarch (),
|
||||
NULL);
|
||||
SELF_CHECK (regcache_access::current_regcache_size () == 3);
|
||||
SELF_CHECK (regcaches_size () == 3);
|
||||
|
||||
/* Get regcache from (target1,ptid2) again, nothing is added to
|
||||
current_regcache. */
|
||||
REGCACHES. */
|
||||
test_get_thread_arch_aspace_regcache (&test_target1, ptid2,
|
||||
target_gdbarch (),
|
||||
NULL);
|
||||
SELF_CHECK (regcache_access::current_regcache_size () == 3);
|
||||
SELF_CHECK (regcaches_size () == 3);
|
||||
|
||||
/* Get regcache from (target2,ptid2), a new regcache is added to
|
||||
current_regcache, since this time we're using a differen
|
||||
target. */
|
||||
REGCACHES, since this time we're using a different target. */
|
||||
test_get_thread_arch_aspace_regcache (&test_target2, ptid2,
|
||||
target_gdbarch (),
|
||||
NULL);
|
||||
SELF_CHECK (regcache_access::current_regcache_size () == 4);
|
||||
SELF_CHECK (regcaches_size () == 4);
|
||||
|
||||
/* Mark that (target1,ptid2) changed. The regcache of (target1,
|
||||
ptid2) should be removed from current_regcache. */
|
||||
ptid2) should be removed from REGCACHES. */
|
||||
registers_changed_ptid (&test_target1, ptid2);
|
||||
SELF_CHECK (regcache_access::current_regcache_size () == 3);
|
||||
SELF_CHECK (regcaches_size () == 3);
|
||||
|
||||
/* Get the regcache from (target2,ptid2) again, confirming the
|
||||
registers_changed_ptid call above did not delete it. */
|
||||
test_get_thread_arch_aspace_regcache (&test_target2, ptid2,
|
||||
target_gdbarch (),
|
||||
NULL);
|
||||
SELF_CHECK (regcache_access::current_regcache_size () == 3);
|
||||
SELF_CHECK (regcaches_size () == 3);
|
||||
|
||||
/* Confirm that marking all regcaches of all targets as changed
|
||||
clears current_regcache. */
|
||||
clears REGCACHES. */
|
||||
registers_changed_ptid (nullptr, minus_one_ptid);
|
||||
SELF_CHECK (regcache_access::current_regcache_size () == 0);
|
||||
SELF_CHECK (regcaches_size () == 0);
|
||||
}
|
||||
|
||||
class target_ops_no_register : public test_target_ops
|
||||
@@ -1828,6 +1871,66 @@ cooked_write_test (struct gdbarch *gdbarch)
|
||||
}
|
||||
}
|
||||
|
||||
/* Verify that when two threads with the same ptid exist (from two different
|
||||
targets) and one of them changes ptid, we only update the appropriate
|
||||
regcaches. */
|
||||
|
||||
static void
|
||||
regcache_thread_ptid_changed ()
|
||||
{
|
||||
/* Any arch will do. */
|
||||
gdbarch *arch = current_inferior ()->gdbarch;
|
||||
|
||||
/* Prepare two targets with one thread each, with the same ptid. */
|
||||
scoped_mock_context<test_target_ops> target1 (arch);
|
||||
scoped_mock_context<test_target_ops> target2 (arch);
|
||||
target2.mock_inferior.next = &target1.mock_inferior;
|
||||
|
||||
ptid_t old_ptid (111, 222);
|
||||
ptid_t new_ptid (111, 333);
|
||||
|
||||
target1.mock_inferior.pid = old_ptid.pid ();
|
||||
target1.mock_thread.ptid = old_ptid;
|
||||
target2.mock_inferior.pid = old_ptid.pid ();
|
||||
target2.mock_thread.ptid = old_ptid;
|
||||
|
||||
gdb_assert (regcaches.empty ());
|
||||
|
||||
/* Populate the regcaches container. */
|
||||
get_thread_arch_aspace_regcache (&target1.mock_target, old_ptid, arch,
|
||||
nullptr);
|
||||
get_thread_arch_aspace_regcache (&target2.mock_target, old_ptid, arch,
|
||||
nullptr);
|
||||
|
||||
/* Return the count of regcaches for (TARGET, PTID) in REGCACHES. */
|
||||
auto regcache_count = [] (process_stratum_target *target, ptid_t ptid)
|
||||
-> int
|
||||
{
|
||||
auto ptid_regc_map_it = regcaches.find (target);
|
||||
if (ptid_regc_map_it != regcaches.end ())
|
||||
{
|
||||
auto &ptid_regc_map = ptid_regc_map_it->second;
|
||||
auto range = ptid_regc_map.equal_range (ptid);
|
||||
return std::distance (range.first, range.second);
|
||||
}
|
||||
return 0;
|
||||
};
|
||||
|
||||
gdb_assert (regcaches.size () == 2);
|
||||
gdb_assert (regcache_count (&target1.mock_target, old_ptid) == 1);
|
||||
gdb_assert (regcache_count (&target1.mock_target, new_ptid) == 0);
|
||||
gdb_assert (regcache_count (&target2.mock_target, old_ptid) == 1);
|
||||
gdb_assert (regcache_count (&target2.mock_target, new_ptid) == 0);
|
||||
|
||||
thread_change_ptid (&target1.mock_target, old_ptid, new_ptid);
|
||||
|
||||
gdb_assert (regcaches.size () == 2);
|
||||
gdb_assert (regcache_count (&target1.mock_target, old_ptid) == 0);
|
||||
gdb_assert (regcache_count (&target1.mock_target, new_ptid) == 1);
|
||||
gdb_assert (regcache_count (&target2.mock_target, old_ptid) == 1);
|
||||
gdb_assert (regcache_count (&target2.mock_target, new_ptid) == 0);
|
||||
}
|
||||
|
||||
} // namespace selftests
|
||||
#endif /* GDB_SELF_TEST */
|
||||
|
||||
@@ -1839,18 +1942,19 @@ _initialize_regcache ()
|
||||
= gdbarch_data_register_post_init (init_regcache_descr);
|
||||
|
||||
gdb::observers::target_changed.attach (regcache_observer_target_changed);
|
||||
gdb::observers::thread_ptid_changed.attach
|
||||
(regcache::regcache_thread_ptid_changed);
|
||||
gdb::observers::thread_ptid_changed.attach (regcache_thread_ptid_changed);
|
||||
|
||||
add_com ("flushregs", class_maintenance, reg_flush_command,
|
||||
_("Force gdb to flush its register cache (maintainer command)."));
|
||||
|
||||
#if GDB_SELF_TEST
|
||||
selftests::register_test ("current_regcache", selftests::current_regcache_test);
|
||||
selftests::register_test ("regcaches", selftests::regcaches_test);
|
||||
|
||||
selftests::register_test_foreach_arch ("regcache::cooked_read_test",
|
||||
selftests::cooked_read_test);
|
||||
selftests::register_test_foreach_arch ("regcache::cooked_write_test",
|
||||
selftests::cooked_write_test);
|
||||
selftests::register_test ("regcache_thread_ptid_changed",
|
||||
selftests::regcache_thread_ptid_changed);
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -22,7 +22,6 @@
|
||||
|
||||
#include "gdbsupport/common-regcache.h"
|
||||
#include "gdbsupport/function-view.h"
|
||||
#include <forward_list>
|
||||
|
||||
struct regcache;
|
||||
struct regset;
|
||||
@@ -397,13 +396,10 @@ public:
|
||||
debug. */
|
||||
void debug_print_register (const char *func, int regno);
|
||||
|
||||
static void regcache_thread_ptid_changed (ptid_t old_ptid, ptid_t new_ptid);
|
||||
protected:
|
||||
regcache (process_stratum_target *target, gdbarch *gdbarch,
|
||||
const address_space *aspace);
|
||||
|
||||
static std::forward_list<regcache *> current_regcache;
|
||||
|
||||
private:
|
||||
|
||||
/* Helper function for transfer_regset. Copies across a single register. */
|
||||
@@ -437,11 +433,10 @@ private:
|
||||
get_thread_arch_aspace_regcache (process_stratum_target *target, ptid_t ptid,
|
||||
struct gdbarch *gdbarch,
|
||||
struct address_space *aspace);
|
||||
|
||||
friend void
|
||||
registers_changed_ptid (process_stratum_target *target, ptid_t ptid);
|
||||
};
|
||||
|
||||
using regcache_up = std::unique_ptr<regcache>;
|
||||
|
||||
class readonly_detached_regcache : public readable_regcache
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -33,8 +33,8 @@
|
||||
#include "target-descriptions.h"
|
||||
#include "target.h"
|
||||
#include "value.h"
|
||||
|
||||
#include "sparc64-tdep.h"
|
||||
#include <forward_list>
|
||||
|
||||
/* This file implements the SPARC 64-bit ABI as defined by the
|
||||
section "Low-Level System Information" of the SPARC Compliance
|
||||
|
||||
@@ -775,7 +775,7 @@ thread_change_ptid (process_stratum_target *targ,
|
||||
tp = find_thread_ptid (inf, old_ptid);
|
||||
tp->ptid = new_ptid;
|
||||
|
||||
gdb::observers::thread_ptid_changed.notify (old_ptid, new_ptid);
|
||||
gdb::observers::thread_ptid_changed.notify (targ, old_ptid, new_ptid);
|
||||
}
|
||||
|
||||
/* See gdbthread.h. */
|
||||
|
||||
@@ -32,6 +32,8 @@
|
||||
thread_stratum target that might want to sit on top.
|
||||
*/
|
||||
|
||||
#include <functional>
|
||||
|
||||
class ptid_t
|
||||
{
|
||||
public:
|
||||
@@ -143,6 +145,20 @@ private:
|
||||
long m_tid;
|
||||
};
|
||||
|
||||
/* Functor to hash a ptid. */
|
||||
|
||||
struct hash_ptid
|
||||
{
|
||||
size_t operator() (const ptid_t &ptid) const
|
||||
{
|
||||
std::hash<long> long_hash;
|
||||
|
||||
return (long_hash (ptid.pid ())
|
||||
+ long_hash (ptid.lwp ())
|
||||
+ long_hash (ptid.tid ()));
|
||||
}
|
||||
};
|
||||
|
||||
/* The null or zero ptid, often used to indicate no process. */
|
||||
|
||||
extern const ptid_t null_ptid;
|
||||
|
||||
Reference in New Issue
Block a user