summaryrefslogtreecommitdiff
path: root/data/eo/eo_gdb.py
blob: 76b8fbd824f18a9cb4d7bcc1b72bf186895f3ebf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
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_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()