diff options
Diffstat (limited to 'gdb/regcache.c')
-rw-r--r-- | gdb/regcache.c | 130 |
1 files changed, 105 insertions, 25 deletions
diff --git a/gdb/regcache.c b/gdb/regcache.c index d9af4539ab9..91d3202b94b 100644 --- a/gdb/regcache.c +++ b/gdb/regcache.c @@ -319,11 +319,14 @@ reg_buffer::assert_regnum (int regnum) const 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. */ +/* Type holding regcaches for a given pid. */ -using target_ptid_regcache_map - = std::unordered_map<process_stratum_target *, ptid_regcache_map>; +using pid_ptid_regcache_map = std::unordered_map<int, ptid_regcache_map>; + +/* Type holding regcaches for a given target. */ + +using target_pid_ptid_regcache_map + = std::unordered_map<process_stratum_target *, pid_ptid_regcache_map>; /* Global structure containing the existing regcaches. */ @@ -331,7 +334,7 @@ using target_ptid_regcache_map recording if the register values have been changed (eg. by the user). Therefore all registers must be written back to the target when appropriate. */ -static target_ptid_regcache_map regcaches; +static target_pid_ptid_regcache_map regcaches; struct regcache * get_thread_arch_aspace_regcache (process_stratum_target *target, @@ -340,8 +343,11 @@ get_thread_arch_aspace_regcache (process_stratum_target *target, { gdb_assert (target != nullptr); - /* Find the ptid -> regcache map for this target. */ - auto &ptid_regc_map = regcaches[target]; + /* Find the map for this target. */ + pid_ptid_regcache_map &pid_ptid_regc_map = regcaches[target]; + + /* Find the map for this pid. */ + ptid_regcache_map &ptid_regc_map = pid_ptid_regc_map[ptid.pid ()]; /* Check first if a regcache for this arch already exists. */ auto range = ptid_regc_map.equal_range (ptid); @@ -436,12 +442,19 @@ static void regcache_thread_ptid_changed (process_stratum_target *target, ptid_t old_ptid, ptid_t new_ptid) { - auto ptid_regc_map_it = regcaches.find (target); + /* Look up map for target. */ + auto pid_ptid_regc_map_it = regcaches.find (target); + if (pid_ptid_regc_map_it == regcaches.end ()) + return; - if (ptid_regc_map_it == regcaches.end ()) + /* Look up map for pid. */ + pid_ptid_regcache_map &pid_ptid_regc_map = pid_ptid_regc_map_it->second; + auto ptid_regc_map_it = pid_ptid_regc_map.find (old_ptid.pid ()); + if (ptid_regc_map_it == pid_ptid_regc_map.end ()) return; - auto &ptid_regc_map = ptid_regc_map_it->second; + /* Update all regcaches belonging to old_ptid. */ + ptid_regcache_map &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;) { @@ -478,15 +491,43 @@ registers_changed_ptid (process_stratum_target *target, ptid_t ptid) /* Delete all the regcaches of all targets. */ regcaches.clear (); } + else if (ptid.is_pid ()) + { + /* Non-NULL target and pid ptid, delete all regcaches belonging + to this (TARGET, PID). */ + + /* Look up map for target. */ + auto pid_ptid_regc_map_it = regcaches.find (target); + if (pid_ptid_regc_map_it != regcaches.end ()) + { + pid_ptid_regcache_map &pid_ptid_regc_map + = pid_ptid_regc_map_it->second; + + pid_ptid_regc_map.erase (ptid.pid ()); + } + } 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 ()) + to this (TARGET, PTID). */ + + /* Look up map for target. */ + auto pid_ptid_regc_map_it = regcaches.find (target); + if (pid_ptid_regc_map_it != regcaches.end ()) { - auto &ptid_regc_map = ptid_regc_map_it->second; - ptid_regc_map.erase (ptid); + pid_ptid_regcache_map &pid_ptid_regc_map + = pid_ptid_regc_map_it->second; + + /* Look up map for pid. */ + auto ptid_regc_map_it + = pid_ptid_regc_map.find (ptid.pid ()); + if (ptid_regc_map_it != pid_ptid_regc_map.end ()) + { + ptid_regcache_map &ptid_regc_map + = ptid_regc_map_it->second; + + ptid_regc_map.erase (ptid); + } } } else @@ -1479,10 +1520,23 @@ static size_t regcaches_size () { size_t size = 0; - for (auto it = regcaches.begin (); it != regcaches.end (); ++it) + + for (auto pid_ptid_regc_map_it = regcaches.cbegin (); + pid_ptid_regc_map_it != regcaches.cend (); + ++pid_ptid_regc_map_it) { - auto &ptid_regc_map = it->second; - size += ptid_regc_map.size (); + const pid_ptid_regcache_map &pid_ptid_regc_map + = pid_ptid_regc_map_it->second; + + for (auto ptid_regc_map_it = pid_ptid_regc_map.cbegin (); + ptid_regc_map_it != pid_ptid_regc_map.cend (); + ++ptid_regc_map_it) + { + const ptid_regcache_map &ptid_regc_map + = ptid_regc_map_it->second; + + size += ptid_regc_map.size (); + } } return size; @@ -1493,13 +1547,21 @@ regcaches_size () static int regcache_count (process_stratum_target *target, ptid_t ptid) { - auto ptid_regc_map_it = regcaches.find (target); - if (ptid_regc_map_it != regcaches.end ()) + /* Look up map for target. */ + auto pid_ptid_regc_map_it = regcaches.find (target); + if (pid_ptid_regc_map_it != regcaches.end ()) { - auto &ptid_regc_map = ptid_regc_map_it->second; - auto range = ptid_regc_map.equal_range (ptid); + pid_ptid_regcache_map &pid_ptid_regc_map = pid_ptid_regc_map_it->second; - return std::distance (range.first, range.second); + /* Look map for pid. */ + auto ptid_regc_map_it = pid_ptid_regc_map.find (ptid.pid ()); + if (ptid_regc_map_it != pid_ptid_regc_map.end ()) + { + ptid_regcache_map &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; @@ -1622,6 +1684,22 @@ registers_changed_ptid_target_test () SELF_CHECK (regcache_count (&data->test_target2, ptid_t (2, 2)) == 1); } +/* Test marking regcaches of a specific (target, pid) as changed. */ + +static void +registers_changed_ptid_target_pid_test () +{ + regcache_test_data_up data = populate_regcaches_for_test (); + + registers_changed_ptid (&data->test_target1, ptid_t (2)); + SELF_CHECK (regcaches_size () == 9); + + /* Regcaches from target1 should not exist, while regcaches from target2 + should exist. */ + SELF_CHECK (regcache_count (&data->test_target1, ptid_t (2, 2)) == 0); + SELF_CHECK (regcache_count (&data->test_target2, ptid_t (2, 2)) == 1); +} + /* Test marking regcaches of a specific (target, ptid) as changed. */ static void @@ -2012,10 +2090,12 @@ _initialize_regcache () selftests::get_thread_arch_aspace_regcache_test); selftests::register_test ("registers_changed_ptid_all", selftests::registers_changed_ptid_all_test); + selftests::register_test ("registers_changed_ptid_target", + selftests::registers_changed_ptid_target_test); + selftests::register_test ("registers_changed_ptid_target_pid", + selftests::registers_changed_ptid_target_pid_test); selftests::register_test ("registers_changed_ptid_target_ptid", selftests::registers_changed_ptid_target_ptid_test); - selftests::register_test ("registers_changed_ptid_target", - selftests::registers_changed_ptid_target_test); selftests::register_test_foreach_arch ("regcache::cooked_read_test", selftests::cooked_read_test); |