forked from enlightenment/efl
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
146 lines
4.4 KiB
146 lines
4.4 KiB
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 *)')) |
|
|
|
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_void_ptr = gdb.parse_and_eval('(_Eo_Object *) 0') |
|
null_eo_object_ptr = gdb.parse_and_eval('(_Eo_Object *) 0') |
|
zero_uintptr_t = gdb.parse_and_eval('(uintptr_t) 0') |
|
|
|
|
|
class Eo_resolve(gdb.Function): |
|
def __init__(self): |
|
gdb.Function.__init__(self, 'eo_resolve') |
|
|
|
def invoke(self, arg): |
|
obj_id = int(str(arg.cast(zero_uintptr_t.type)), 0) |
|
|
|
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_eo_object_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_eo_object_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_eo_object_ptr |
|
|
|
return entry['ptr'] |
|
|
|
|
|
Eo_resolve() |
|
|
|
|
|
class Eo_data_get(gdb.Function): |
|
def __init__(self): |
|
gdb.Function.__init__(self, 'eo_data_get') |
|
|
|
def invoke(self, ptr, kls_name): |
|
ptr = ptr.cast(null_eo_object_ptr.type) # Cast to correct type |
|
|
|
if int(ptr) == 0: |
|
gdb.write('Object is not a valid pointer (NULL).\n') |
|
return null_void_ptr |
|
|
|
kls_name = kls_name.string() |
|
extns = ptr['klass']['mro'] |
|
kls = None |
|
|
|
i = 0 |
|
while int(extns[i]) != 0: |
|
if extns[i]['desc']['name'].string() == kls_name: |
|
kls = extns[i] |
|
i += 1 |
|
|
|
if kls is None: |
|
gdb.write('Class "{}" not found in the object mro.\n' |
|
.format(kls_name)) |
|
return null_void_ptr |
|
|
|
# Check if not mixin |
|
if int(kls['desc']['type'].cast(zero_uintptr_t.type)) != 3: |
|
return gdb.parse_and_eval('(void *) (((char *) {}) + {})' |
|
.format(ptr, kls['data_offset'])) |
|
else: |
|
extn_off = ptr['klass']['extn_data_off'] |
|
if int(extn_off) == 0: |
|
return null_void_ptr |
|
|
|
i = 0 |
|
while int(extn_off[i]['klass']) != 0: |
|
kls = extn_off[i]['klass'] |
|
if kls['desc']['name'].string() == kls_name: |
|
return gdb.parse_and_eval('(void *) (((char *) {}) + {})' |
|
.format(ptr, kls['data_offset'])) |
|
i += 1 |
|
|
|
return null_void_ptr |
|
|
|
|
|
Eo_data_get()
|
|
|