diff options
author | Luke Chen <luke.chen@mongodb.com> | 2022-05-09 15:45:27 +1000 |
---|---|---|
committer | Evergreen Agent <no-reply@evergreen.mongodb.com> | 2022-05-09 06:19:32 +0000 |
commit | 20c06486b1efec6cf6dbd3b69890b07cedbe449f (patch) | |
tree | 446aa484068f935ca6cbb5e84e552845be5c25f8 | |
parent | a9a4d9997802371464c865e62ccd209a35d3903d (diff) | |
download | mongo-20c06486b1efec6cf6dbd3b69890b07cedbe449f.tar.gz |
Import wiredtiger: 96e1178c2cfb2adc2e53d2fbc7e512025ddf6cc2 from branch mongodb-master
ref: b9c5631ea0..96e1178c2c
for: 6.1.0-rc0
WT-8158 Add gdb helper scripts to WiredTiger repository
-rw-r--r-- | src/third_party/wiredtiger/import.data | 2 | ||||
-rw-r--r-- | src/third_party/wiredtiger/tools/gdb/dump_row_int.gdb | 66 | ||||
-rw-r--r-- | src/third_party/wiredtiger/tools/gdb/wt.gdb | 11 | ||||
-rw-r--r-- | src/third_party/wiredtiger/tools/gdb/wt_debug_script_update.py | 150 |
4 files changed, 228 insertions, 1 deletions
diff --git a/src/third_party/wiredtiger/import.data b/src/third_party/wiredtiger/import.data index d87ef49654a..92864186e3c 100644 --- a/src/third_party/wiredtiger/import.data +++ b/src/third_party/wiredtiger/import.data @@ -2,5 +2,5 @@ "vendor": "wiredtiger", "github": "wiredtiger/wiredtiger.git", "branch": "mongodb-master", - "commit": "b9c5631ea09739586d6b76c2d4e11903bb2bccec" + "commit": "96e1178c2cfb2adc2e53d2fbc7e512025ddf6cc2" } diff --git a/src/third_party/wiredtiger/tools/gdb/dump_row_int.gdb b/src/third_party/wiredtiger/tools/gdb/dump_row_int.gdb new file mode 100644 index 00000000000..d83e54b0ed8 --- /dev/null +++ b/src/third_party/wiredtiger/tools/gdb/dump_row_int.gdb @@ -0,0 +1,66 @@ +# A helper script to dump row store internal page keys. +# Usage: dump_row_int_keys <page> + +# Dump keys from a row store internal page. +# Has one argument which is the page. +define dump_row_int_keys + set pagination off + set $i = 0 + set $page = $arg0 + while $i < $page->u->intl->__index.entries + set $ikey = $page->u->intl->__index->index[$i].key.ikey + set $v = (uintptr_t)$ikey + + set $keyp = 0 + set $size = 0 + set $key_location = "" + + if $v & 0x1 + set $key_location = "DSK:" +# Relevant code snippets from WiredTiger we are trying to simulate. +# #define WT_IK_FLAG 0x01 +# #define WT_IK_DECODE_KEY_LEN(v) ((v) >> 32) +# #define WT_IK_DECODE_KEY_OFFSET(v) (((v)&0xFFFFFFFF) >> 1) +# #define WT_PAGE_REF_OFFSET(page, o) ((void *)((uint8_t *)((page)->dsk) + (o))) +# if (v & WT_IK_FLAG) { +# *(void **)keyp = WT_PAGE_REF_OFFSET(page, WT_IK_DECODE_KEY_OFFSET(v)); +# *sizep = WT_IK_DECODE_KEY_LEN(v); + set $key_offset = (($v) & 0xFFFFFFFF) >> 1 + set $keyp = ((void *)((uint8_t *)($page->dsk) + $key_offset)) + set $size = ($v) >> 32 + else + set $key_location = "MEM:" + set $keyp = ((void *)((uint8_t *)($ikey) + 8)) + set $size = ((WT_IKEY*)$ikey)->size + end + set $sz_pad = "" + if $size < 10 + set $sz_pad = " " + else + if $size < 100 + set $sz_pad = " " + end + end + set $off_pad = "" + if $i < 10 + set $off_pad = " " + else + if $i < 100 + set $off_pad = " " + else + if $i < 1000 + set $off_pad = " " + end + end + end + printf "%s%u:%s%s%u: ", $off_pad, $i, $key_location, $sz_pad, $size + set $j = 0 + while $j < $size + printf "%c", ((char*)$keyp)[$j] + set $j = $j + 1 + end + printf "\n" + + set $i = $i + 1 + end +end diff --git a/src/third_party/wiredtiger/tools/gdb/wt.gdb b/src/third_party/wiredtiger/tools/gdb/wt.gdb new file mode 100644 index 00000000000..cd446e4f1ca --- /dev/null +++ b/src/third_party/wiredtiger/tools/gdb/wt.gdb @@ -0,0 +1,11 @@ +# Usage: source <path_to>/wt.gdb +# This is a thin wrapper around the other files that hold actual helper functions. + +# Assume GDB is run from a build directory one level deep in the tree. +# TODO: Find a better solution +directory ../tools/gdb_commands + +# Source the known gdb helpers +source dump_row_int.gdb +source wt_debug_script_update.py + diff --git a/src/third_party/wiredtiger/tools/gdb/wt_debug_script_update.py b/src/third_party/wiredtiger/tools/gdb/wt_debug_script_update.py new file mode 100644 index 00000000000..13a04c18ef9 --- /dev/null +++ b/src/third_party/wiredtiger/tools/gdb/wt_debug_script_update.py @@ -0,0 +1,150 @@ +import gdb +import bson +from pprint import pprint + +# Usage examples: +# coll_dh = get_data_handle(conn, 'file:collection-5550--7194480883124807592.wt') +# dump_handle(coll_dh) +# index_dh = get_data_handle(conn, 'file:index-5558--7194480883124807592.wt') +# dump_handle(index_dh) + +def dbg(ident, var): + print('----------') + if type(var) == gdb.Value: + print('{}: ({}*){}'.format(ident, var.type, var.address)) + else: + print(ident) + print(' ' + str(type(var))) + methods = dir(var) + out = [name for name in methods if not name.startswith("__")] + for item in out: + print(' ' + item) + + if type(var) == gdb.Value: + print('\n Fields:') + print('\t' + '\n\t'.join(str(var).split('\n'))) + +conn_impl_ptr = gdb.lookup_type("WT_CONNECTION_IMPL").pointer() +dbg('impl', conn_impl_ptr) + +conn = gdb.parse_and_eval("session->iface->connection").reinterpret_cast(conn_impl_ptr).dereference() +dbg('conn', conn) + +def walk_wt_list(lst): + ret = [] + node = conn['dhqh']['tqh_first'] + #dbg('node', node) + while True: + if not node: + break + ret.append(node.dereference()) + node = node['q']['tqe_next'] + + return ret + +def get_data_handle(conn, handle_name): + #dbg('datahandles', conn['dhqh']) + ret = None + for handle in walk_wt_list(conn['dhqh']): + #print("Handle: " + str(handle['name'])) + if handle['name'].string() == handle_name: + ret = handle + + return ret + +def get_btree_handle(dhandle): + btree = gdb.lookup_type('WT_BTREE').pointer() + return dhandle['handle'].reinterpret_cast(btree).dereference() + +def dump_update_chain(update_chain): + while True: + if not update_chain: + print(' λ') + break + #dbg('update', update_chain) + wt_val = update_chain.dereference() + obj = None + #dbg('wt_val', wt_val) + val_bytes = gdb.selected_inferior().read_memory(wt_val['data'], wt_val['size']) + can_bson = wt_val['type'] == 3 + if can_bson: + try: + obj = bson.decode_all(val_bytes)[0] + except: + pass + print(' ' + '\n '.join(str(wt_val).split('\n')) + " " + str(obj) + " =>") + + update_chain = update_chain['next'] + +def dump_insert_list(wt_insert): + key_struct = wt_insert['u']['key'] + key = gdb.selected_inferior().read_memory(int(wt_insert.address) + key_struct['offset'], key_struct['size']).tobytes() + print('Key: ' + str(key)) + print('Value:') + update_chain = wt_insert['upd'] + dump_update_chain(update_chain) + +def dump_skip_list(wt_insert_head): + wt_insert = wt_insert_head['head'][0] + idx = 0 + while True: + if not wt_insert: + break + dump_insert_list(wt_insert.dereference()) + #dbg('insert' + str(idx), wt_insert.dereference()) + idx+=1 + wt_insert = wt_insert['next'][0] + +def dump_modified(leaf_page): + print("Modify:") + if not leaf_page['modify']: + print("No modifies") + return + + leaf_modify = leaf_page['modify'].dereference() + #dbg('modify', leaf_modify) + row_leaf_insert = leaf_modify['u2']['row_leaf']['insert'] + #dbg('row store', row_leaf_modify) + if not row_leaf_insert: + print("No insert list") + else: + print("Insert list:") + dump_skip_list(row_leaf_insert.dereference().dereference()) + + row_leaf_update = leaf_modify['u2']['row_leaf']['update'] + if not row_leaf_update: + print("No update list") + else: + print("Update list:") + leaf_num_entries = int(leaf_page['entries']) + for i in range(0, leaf_num_entries): + dump_update_chain(row_leaf_update[i]) + +def dump_disk(leaf_page): + leaf_num_entries = int(leaf_page['entries']) + dbg('in-memory page:', leaf_page) + dsk = leaf_page['dsk'].dereference() + if int(dsk.address) == 0: + print("No page loaded from disk.") + return + dbg('on-disk page:', dsk) + wt_page_header_size = 28 + wt_block_header_size = 12 + page_bytes = gdb.selected_inferior().read_memory(int(dsk.address) + wt_page_header_size + wt_block_header_size, int(dsk['mem_size'])).tobytes() + print("Dsk:\n" + str(page_bytes)) + +def dump_handle(dhandle): + print("Dumping: " + dhandle['name'].string()) + btree = get_btree_handle(dhandle) + root = btree['root'] + root_page = root['page'].dereference() + dbg('btree', get_btree_handle(user)) + dbg('root', btree['root']) + dbg('root page', root_page) + rpindex = root_page['u']['intl']['__index'].dereference() + dbg('rpindex', rpindex) + dbg('rp-pre-index', rpindex['index'].dereference().dereference()) + leaf_page = rpindex['index'].dereference().dereference()['page'].dereference() + dbg('leaf', leaf_page) + dump_disk(leaf_page) + dump_modified(leaf_page) |