import gdb """ All of this script relies heavily on Eo internals and will break if they change. Need to make sure this is always in sync. """ ptr_size = int(gdb.parse_and_eval('sizeof(void *)')) SHIFT_MID_TABLE_ID = 0x30 MASK_MID_TABLE_ID = 0x7ff SHIFT_TABLE_ID = 0x25 MASK_TABLE_ID = 0x7ff SHIFT_ENTRY_ID = 0x1a MASK_ENTRY_ID = 0x7ff MASK_GENERATIONS = 0x3ffffff MASK_OBJ_TAG = 0x4000000000000000 if ptr_size == 4: # 32 bits BITS_MID_TABLE_ID = 5 BITS_TABLE_ID = 5 BITS_ENTRY_ID = 11 BITS_GENERATION_COUNTER = 6 BITS_DOMAIN = 2 BITS_CLASS = 1 REF_TAG_SHIFT = 30 SUPER_TAG_SHIFT = 31 DROPPED_TABLES = 0 DROPPED_ENTRIES = 4 else: # 64 bits BITS_MID_TABLE_ID = 11 BITS_TABLE_ID = 11 BITS_ENTRY_ID = 11 BITS_GENERATION_COUNTER = 26 BITS_DOMAIN = 2 BITS_CLASS = 1 REF_TAG_SHIFT = 62 SUPER_TAG_SHIFT = 63 DROPPED_TABLES = 2 DROPPED_ENTRIES = 3 # /* Shifts macros to manipulate the Eo id */ SHIFT_DOMAIN = (BITS_MID_TABLE_ID + BITS_TABLE_ID + BITS_ENTRY_ID + BITS_GENERATION_COUNTER) SHIFT_MID_TABLE_ID = (BITS_TABLE_ID + BITS_ENTRY_ID + BITS_GENERATION_COUNTER) SHIFT_TABLE_ID = (BITS_ENTRY_ID + BITS_GENERATION_COUNTER) SHIFT_ENTRY_ID = (BITS_GENERATION_COUNTER) # /* Maximum ranges */ MAX_DOMAIN = (1 << BITS_DOMAIN) MAX_MID_TABLE_ID = (1 << BITS_MID_TABLE_ID) MAX_TABLE_ID = ((1 << BITS_TABLE_ID) - DROPPED_TABLES) MAX_ENTRY_ID = ((1 << BITS_ENTRY_ID) - DROPPED_ENTRIES) MAX_GENERATIONS = (1 << BITS_GENERATION_COUNTER) # /* Masks */ MASK_DOMAIN = (MAX_DOMAIN - 1) MASK_MID_TABLE_ID = (MAX_MID_TABLE_ID - 1) MASK_TABLE_ID = ((1 << BITS_TABLE_ID) - 1) MASK_ENTRY_ID = ((1 << BITS_ENTRY_ID) - 1) MASK_GENERATIONS = (MAX_GENERATIONS - 1) MASK_OBJ_TAG = (1 << (REF_TAG_SHIFT)) null_ptr = gdb.parse_and_eval('(_Eo_Object *) 0') class Eo_resolve(gdb.Function): def __init__(self): gdb.Function.__init__(self, 'eo_resolve') def invoke(self, arg): obj_id = int(arg) mid_table_id = (obj_id >> SHIFT_MID_TABLE_ID) & MASK_MID_TABLE_ID table_id = (obj_id >> SHIFT_TABLE_ID) & MASK_TABLE_ID entry_id = (obj_id >> SHIFT_ENTRY_ID) & MASK_ENTRY_ID tag_bit = (obj_id) & MASK_OBJ_TAG generation = obj_id & MASK_GENERATIONS if (obj_id == 0) or (tag_bit == 0): gdb.write('Pointer is NULL or not a valid object.\n') return null_ptr entries = gdb.parse_and_eval('_eo_gdb_main_domain->tables[0]->' + 'eo_ids_tables[{0}]'.format(mid_table_id)) if int(entries) == 0: gdb.write('Pointer is not a valid object.\n') return null_ptr entry = entries[table_id]['entries'][entry_id] if (not entry['active']) or (int(entry['generation']) != generation): gdb.write('Pointer is no longer active.\n') return null_ptr return entry['ptr'] Eo_resolve()