summaryrefslogtreecommitdiff
path: root/data/eo/eo_gdb.py
diff options
context:
space:
mode:
authorTom Hacohen <tom@stosb.com>2016-11-18 08:44:21 +0000
committerTom Hacohen <tom@stosb.com>2016-11-18 11:48:07 +0000
commit79d76fb25ece4ffbf5785b4be2b030f062ef9f2c (patch)
tree7c492c5dbdef8f39e35f143a9fc708ae81db7db6 /data/eo/eo_gdb.py
parent3dd51bf53de9003e0e3ba396a5c0f2b10c44c1fd (diff)
Eo gdb: add a way to resolve Eo ids from GDB without a running process
Normally when debugging Eo with gdb you can just use any of the internal eo functions to resolve the id to its internal pointer. However, when loading a coredump you can't execute any code, not even the id resolve code. This change adds a gdb function that resolves the id to its pointer form without executing any code in the process space. This plugin is essentially the id resolve code written in python as a gdb function. Usage: Print the pointer: (gdb) print $eo_resolve(obj) $1 = (_Eo_Object *) 0x5555559bbe70 Use it directly (e.g. to print the class name): (gdb) $eo_resolve(obj)->klass->desc.name This plugin requires that the coredump would be loaded with the exact same libeo.so binary (or at least one that hasn't changed eo internals), and that the debug symbols for libeo.so would be available for gdb to use. Note: This feature is incomplete and only resolves IDs that are owned by the main thread and in the main domain. This is not a big issue at the moment, because almost all of our IDs are like that. @feature
Diffstat (limited to '')
-rw-r--r--data/eo/eo_gdb.py104
1 files changed, 102 insertions, 2 deletions
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 @@
1# Implement eo_break that'll break on a macro/subid/whatever.
2
3import gdb 1import gdb
4 2
3"""
4All of this script relies heavily on Eo internals and will break if they
5change. Need to make sure this is always in sync.
6"""
7
8ptr_size = int(gdb.parse_and_eval('sizeof(void *)'))
9
10SHIFT_MID_TABLE_ID = 0x30
11MASK_MID_TABLE_ID = 0x7ff
12SHIFT_TABLE_ID = 0x25
13MASK_TABLE_ID = 0x7ff
14SHIFT_ENTRY_ID = 0x1a
15MASK_ENTRY_ID = 0x7ff
16MASK_GENERATIONS = 0x3ffffff
17MASK_OBJ_TAG = 0x4000000000000000
18
19if ptr_size == 4:
20 # 32 bits
21 BITS_MID_TABLE_ID = 5
22 BITS_TABLE_ID = 5
23 BITS_ENTRY_ID = 11
24 BITS_GENERATION_COUNTER = 6
25 BITS_DOMAIN = 2
26 BITS_CLASS = 1
27 REF_TAG_SHIFT = 30
28 SUPER_TAG_SHIFT = 31
29 DROPPED_TABLES = 0
30 DROPPED_ENTRIES = 4
31else:
32 # 64 bits
33 BITS_MID_TABLE_ID = 11
34 BITS_TABLE_ID = 11
35 BITS_ENTRY_ID = 11
36 BITS_GENERATION_COUNTER = 26
37 BITS_DOMAIN = 2
38 BITS_CLASS = 1
39 REF_TAG_SHIFT = 62
40 SUPER_TAG_SHIFT = 63
41 DROPPED_TABLES = 2
42 DROPPED_ENTRIES = 3
43
44# /* Shifts macros to manipulate the Eo id */
45SHIFT_DOMAIN = (BITS_MID_TABLE_ID + BITS_TABLE_ID +
46 BITS_ENTRY_ID + BITS_GENERATION_COUNTER)
47SHIFT_MID_TABLE_ID = (BITS_TABLE_ID +
48 BITS_ENTRY_ID + BITS_GENERATION_COUNTER)
49SHIFT_TABLE_ID = (BITS_ENTRY_ID + BITS_GENERATION_COUNTER)
50SHIFT_ENTRY_ID = (BITS_GENERATION_COUNTER)
51
52# /* Maximum ranges */
53MAX_DOMAIN = (1 << BITS_DOMAIN)
54MAX_MID_TABLE_ID = (1 << BITS_MID_TABLE_ID)
55MAX_TABLE_ID = ((1 << BITS_TABLE_ID) - DROPPED_TABLES)
56MAX_ENTRY_ID = ((1 << BITS_ENTRY_ID) - DROPPED_ENTRIES)
57MAX_GENERATIONS = (1 << BITS_GENERATION_COUNTER)
58
59# /* Masks */
60MASK_DOMAIN = (MAX_DOMAIN - 1)
61MASK_MID_TABLE_ID = (MAX_MID_TABLE_ID - 1)
62MASK_TABLE_ID = ((1 << BITS_TABLE_ID) - 1)
63MASK_ENTRY_ID = ((1 << BITS_ENTRY_ID) - 1)
64MASK_GENERATIONS = (MAX_GENERATIONS - 1)
65MASK_OBJ_TAG = (1 << (REF_TAG_SHIFT))
66
67
68null_ptr = gdb.parse_and_eval('(_Eo_Object *) 0')
69
70
71class Eo_resolve(gdb.Function):
72 def __init__(self):
73 gdb.Function.__init__(self, 'eo_resolve')
74
75 def invoke(self, arg):
76 obj_id = int(arg)
77
78 mid_table_id = (obj_id >> SHIFT_MID_TABLE_ID) & MASK_MID_TABLE_ID
79 table_id = (obj_id >> SHIFT_TABLE_ID) & MASK_TABLE_ID
80 entry_id = (obj_id >> SHIFT_ENTRY_ID) & MASK_ENTRY_ID
81 tag_bit = (obj_id) & MASK_OBJ_TAG
82 generation = obj_id & MASK_GENERATIONS
83
84 if (obj_id == 0) or (tag_bit == 0):
85 gdb.write('Pointer is NULL or not a valid object.\n')
86 return null_ptr
87
88 entries = gdb.parse_and_eval('_eo_gdb_main_domain->tables[0]->' +
89 'eo_ids_tables[{0}]'.format(mid_table_id))
90
91 if int(entries) == 0:
92 gdb.write('Pointer is not a valid object.\n')
93 return null_ptr
94
95 entry = entries[table_id]['entries'][entry_id]
96
97 if (not entry['active']) or (int(entry['generation']) != generation):
98 gdb.write('Pointer is no longer active.\n')
99 return null_ptr
100
101 return entry['ptr']
102
103
104Eo_resolve()