2017-05-01 03:26:56 +03:00
#!/usr/bin/env python3
2020-11-09 07:23:58 +03:00
# SPDX-License-Identifier: LGPL-2.1-or-later
2023-08-09 22:44:36 +03:00
# pylint: disable=consider-using-f-string
2014-10-15 03:31:23 +04:00
import gdb
class sd_dump_hashmaps ( gdb . Command ) :
2016-01-04 22:18:47 +03:00
" dump systemd ' s hashmaps "
def __init__ ( self ) :
2020-05-27 12:20:40 +03:00
super ( ) . __init__ ( " sd_dump_hashmaps " , gdb . COMMAND_DATA , gdb . COMPLETE_NONE )
2016-01-04 22:18:47 +03:00
2023-08-09 22:44:36 +03:00
def invoke ( self , arg , _from_tty ) :
2016-01-04 22:18:47 +03:00
d = gdb . parse_and_eval ( " hashmap_debug_list " )
2020-05-27 12:37:58 +03:00
hashmap_type_info = gdb . parse_and_eval ( " hashmap_type_info " )
2016-01-04 22:18:47 +03:00
uchar_t = gdb . lookup_type ( " unsigned char " )
ulong_t = gdb . lookup_type ( " unsigned long " )
debug_offset = gdb . parse_and_eval ( " (unsigned long)&((HashmapBase*)0)->debug " )
print ( " type, hash, indirect, entries, max_entries, buckets, creator " )
while d :
2020-05-27 12:20:40 +03:00
h = gdb . parse_and_eval ( f " (HashmapBase*)((char*) { int ( d . cast ( ulong_t ) ) } - { debug_offset } ) " )
2016-01-04 22:18:47 +03:00
if h [ " has_indirect " ] :
storage_ptr = h [ " indirect " ] [ " storage " ] . cast ( uchar_t . pointer ( ) )
n_entries = h [ " indirect " ] [ " n_entries " ]
n_buckets = h [ " indirect " ] [ " n_buckets " ]
else :
storage_ptr = h [ " direct " ] [ " storage " ] . cast ( uchar_t . pointer ( ) )
n_entries = h [ " n_direct_entries " ]
2020-05-27 12:37:58 +03:00
n_buckets = hashmap_type_info [ h [ " type " ] ] [ " n_direct_buckets " ]
2016-01-04 22:18:47 +03:00
t = [ " plain " , " ordered " , " set " ] [ int ( h [ " type " ] ) ]
2020-05-28 14:28:11 +03:00
print ( f ' { t } , { h [ " hash_ops " ] } , { bool ( h [ " has_indirect " ] ) } , { n_entries } , { d [ " max_entries " ] } , { n_buckets } , { d [ " func " ] . string ( ) } , { d [ " file " ] . string ( ) } : { d [ " line " ] } ' )
2016-01-04 22:18:47 +03:00
if arg != " " and n_entries > 0 :
2020-05-27 12:37:58 +03:00
dib_raw_addr = storage_ptr + hashmap_type_info [ h [ " type " ] ] [ " entry_size " ] * n_buckets
2016-01-04 22:18:47 +03:00
histogram = { }
2020-05-27 12:20:40 +03:00
for i in range ( 0 , n_buckets ) :
2016-01-04 22:18:47 +03:00
dib = int ( dib_raw_addr [ i ] )
histogram [ dib ] = histogram . get ( dib , 0 ) + 1
2020-05-27 12:20:40 +03:00
for dib in sorted ( histogram ) :
2016-01-04 22:18:47 +03:00
if dib != 255 :
2020-05-27 12:20:40 +03:00
print ( f " { dib : >3 } { histogram [ dib ] : >8 } { float ( histogram [ dib ] / n_entries ) : .0% } of entries " )
2016-01-04 22:18:47 +03:00
else :
2020-05-27 12:20:40 +03:00
print ( f " { dib : >3 } { histogram [ dib ] : >8 } { float ( histogram [ dib ] / n_buckets ) : .0% } of slots " )
s = sum ( dib * count for ( dib , count ) in histogram . items ( ) if dib != 255 ) / n_entries
print ( f " mean DIB of entries: { s } " )
2016-01-04 22:18:47 +03:00
blocks = [ ]
current_len = 1
prev = int ( dib_raw_addr [ 0 ] )
2020-05-27 12:20:40 +03:00
for i in range ( 1 , n_buckets ) :
2016-01-04 22:18:47 +03:00
dib = int ( dib_raw_addr [ i ] )
if ( dib == 255 ) != ( prev == 255 ) :
if prev != 255 :
blocks + = [ [ i , current_len ] ]
current_len = 1
else :
current_len + = 1
prev = dib
if prev != 255 :
blocks + = [ [ i , current_len ] ]
# a block may be wrapped around
if len ( blocks ) > 1 and blocks [ 0 ] [ 0 ] == blocks [ 0 ] [ 1 ] and blocks [ - 1 ] [ 0 ] == n_buckets - 1 :
blocks [ 0 ] [ 1 ] + = blocks [ - 1 ] [ 1 ]
blocks = blocks [ 0 : - 1 ]
print ( " max block: {} " . format ( max ( blocks , key = lambda a : a [ 1 ] ) ) )
print ( " sum block lens: {} " . format ( sum ( b [ 1 ] for b in blocks ) ) )
2020-05-27 12:20:40 +03:00
print ( " mean block len: {} " . format ( sum ( b [ 1 ] for b in blocks ) / len ( blocks ) ) )
2016-01-04 22:18:47 +03:00
d = d [ " debug_list_next " ]
2014-10-15 03:31:23 +04:00
sd_dump_hashmaps ( )