| 244 | } |
| 245 | |
| 246 | void |
| 247 | getDictEntries( |
| 248 | const std::shared_ptr<const AbstractProcessManager>& manager, |
| 249 | Structure<py_dict_v>& dict, |
| 250 | ssize_t& num_items, |
| 251 | std::vector<Python3::PyDictKeyEntry>& valid_entries) |
| 252 | { |
| 253 | assert(manager->versionIsAtLeast(3, 0)); |
| 254 | remote_addr_t keys_addr = dict.getField(&py_dict_v::o_ma_keys); |
| 255 | ssize_t dk_size = 0; |
| 256 | int dk_kind = 0; |
| 257 | |
| 258 | Structure<py_dictkeys_v> keys(manager, keys_addr); |
| 259 | num_items = keys.getField(&py_dictkeys_v::o_dk_nentries); |
| 260 | dk_size = keys.getField(&py_dictkeys_v::o_dk_size); |
| 261 | |
| 262 | if (manager->versionIsAtLeast(3, 11)) { |
| 263 | // We're reusing the o_dk_size offset for dk_log2_size. Fix up the value. |
| 264 | dk_size = 1L << dk_size; |
| 265 | // Added in 3.11 |
| 266 | dk_kind = keys.getField(&py_dictkeys_v::o_dk_kind); |
| 267 | } |
| 268 | if (num_items == 0) { |
| 269 | LOG(DEBUG) << std::hex << std::showbase << "There are no elements in this dict"; |
| 270 | return; |
| 271 | } |
| 272 | /* |
| 273 | * The size in bytes of an indice depends on dk_size: |
| 274 | * |
| 275 | * - 1 byte if dk_size <= 0xff (char*) |
| 276 | * - 2 bytes if dk_size <= 0xffff (int16_t*) |
| 277 | * - 4 bytes if dk_size <= 0xffffffff (int32_t*) |
| 278 | * - 8 bytes otherwise (int64_t*) |
| 279 | */ |
| 280 | ssize_t offset; |
| 281 | if (dk_size <= 0xFF) { |
| 282 | offset = dk_size; |
| 283 | } else if (dk_size <= 0xFFFF) { |
| 284 | offset = 2 * dk_size; |
| 285 | } else if (dk_size <= 0xFFFFFFFF) { |
| 286 | offset = 4 * dk_size; |
| 287 | } else { |
| 288 | offset = 8 * dk_size; |
| 289 | } |
| 290 | |
| 291 | offset_t dk_indices_addr = keys.getFieldRemoteAddress(&py_dictkeys_v::o_dk_indices); |
| 292 | remote_addr_t entries_addr = dk_indices_addr + offset; |
| 293 | |
| 294 | std::vector<Python3::PyDictKeyEntry> raw_entries; |
| 295 | raw_entries.resize(num_items); |
| 296 | |
| 297 | if (dk_kind != 0) { // New PyDictUnicodeEntry |
| 298 | std::vector<Python3_11::PyDictUnicodeEntry> unicode_entries; |
| 299 | unicode_entries.resize(num_items); |
| 300 | manager->copyMemoryFromProcess( |
| 301 | entries_addr, |
| 302 | num_items * sizeof(Python3_11::PyDictUnicodeEntry), |
| 303 | unicode_entries.data()); |
no test coverage detected