MCPcopy Create free account
hub / github.com/bloomberg/pystack / getDictEntries

Function getDictEntries

src/pystack/_pystack/pytypes.cpp:246–324  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

244}
245
246void
247getDictEntries(
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());

Callers 1

loadFromPython3Method · 0.85

Calls 4

LOGClass · 0.85
versionIsAtLeastMethod · 0.80
getFieldRemoteAddressMethod · 0.80
copyMemoryFromProcessMethod · 0.45

Tested by

no test coverage detected