diff --git a/data/eo/eo_gdb.py b/data/eo/eo_gdb.py index 219121034e..995aff450f 100644 --- a/data/eo/eo_gdb.py +++ b/data/eo/eo_gdb.py @@ -1,4 +1,104 @@ -# Implement eo_break that'll break on a macro/subid/whatever. - 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() diff --git a/src/lib/eo/eo.c b/src/lib/eo/eo.c index 46d69441e3..da8f41c24c 100644 --- a/src/lib/eo/eo.c +++ b/src/lib/eo/eo.c @@ -1881,6 +1881,11 @@ _eo_table_del_cb(void *in) _eo_free_ids_tables(data); } +/* FIXME: Support other domains and tables, at the moment only the main + * domain and table. + * This is used by the gdb debug helper script */ +Eo_Id_Data *_eo_gdb_main_domain = NULL; + EAPI Eina_Bool efl_object_init(void) { @@ -1946,6 +1951,7 @@ efl_object_init(void) // specially force eoid data to be creanted so we can switch it to domain 0 Eo_Id_Data *data = _eo_table_data_new(EFL_ID_DOMAIN_MAIN); + _eo_gdb_main_domain = data; if (!data) { EINA_LOG_ERR("Could not allocate main table data");