1163953Srrs# Python hooks for gdb for debugging GCC
2169382Srrs# Copyright (C) 2013-2022 Free Software Foundation, Inc.
3163953Srrs
4163953Srrs# Contributed by David Malcolm <dmalcolm@redhat.com>
5163953Srrs
6163953Srrs# This file is part of GCC.
7163953Srrs
8163953Srrs# GCC is free software; you can redistribute it and/or modify it under
9163953Srrs# the terms of the GNU General Public License as published by the Free
10163953Srrs# Software Foundation; either version 3, or (at your option) any later
11163953Srrs# version.
12163953Srrs
13163953Srrs# GCC is distributed in the hope that it will be useful, but WITHOUT
14163953Srrs# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15163953Srrs# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16163953Srrs# for more details.
17163953Srrs
18163953Srrs# You should have received a copy of the GNU General Public License
19163953Srrs# along with GCC; see the file COPYING3.  If not see
20163953Srrs# <http://www.gnu.org/licenses/>.
21163953Srrs
22163953Srrs"""
23163953SrrsEnabling the debugging hooks
24163953Srrs----------------------------
25163953Srrsgcc/configure (from configure.ac) generates a .gdbinit within the "gcc"
26163953Srrssubdirectory of the build directory, and when run by gdb, this imports
27163953Srrsgcc/gdbhooks.py from the source directory, injecting useful Python code
28163953Srrsinto gdb.
29163953Srrs
30163953SrrsYou may see a message from gdb of the form:
31163954Srrs  "path-to-build/gcc/.gdbinit" auto-loading has been declined by your `auto-load safe-path'
32163953Srrsas a protection against untrustworthy python scripts.  See
33163953Srrs  http://sourceware.org/gdb/onlinedocs/gdb/Auto_002dloading-safe-path.html
34168709Srrs
35166086SrrsThe fix is to mark the paths of the build/gcc directory as trustworthy.
36163953SrrsAn easy way to do so is by adding the following to your ~/.gdbinit script:
37163953Srrs  add-auto-load-safe-path /absolute/path/to/build/gcc
38163953Srrsfor the build directories for your various checkouts of gcc.
39163953Srrs
40168709SrrsIf it's working, you should see the message:
41168709Srrs  Successfully loaded GDB hooks for GCC
42168709Srrsas gdb starts up.
43167598Srrs
44163953SrrsDuring development, I've been manually invoking the code in this way, as a
45166086Srrsprecanned way of printing a variety of different kinds of value:
46163953Srrs
47166086Srrs  gdb \
48166086Srrs    -ex "break expand_gimple_stmt" \
49166086Srrs    -ex "run" \
50166086Srrs    -ex "bt" \
51168709Srrs    --args \
52168709Srrs      ./cc1 foo.c -O3
53170091Srrs
54163953SrrsExamples of output using the pretty-printers
55171167Sgnn--------------------------------------------
56171133SgnnPointer values are generally shown in the form:
57171133Sgnn  <type address extra_info>
58171133Sgnn
59171133SgnnFor example, an opt_pass* might appear as:
60171167Sgnn  (gdb) p pass
61163953Srrs  $2 = <opt_pass* 0x188b600 "expand"(170)>
62163953Srrs
63163953SrrsThe name of the pass is given ("expand"), together with the
64163953Srrsstatic_pass_number.
65171259Sdelphij
66163953SrrsNote that you can dereference the pointer in the normal way:
67165647Srrs  (gdb) p *pass
68163953Srrs  $4 = {type = RTL_PASS, name = 0x120a312 "expand",
69163953Srrs  [etc, ...snipped...]
70163953Srrs
71163953Srrsand you can suppress pretty-printers using /r (for "raw"):
72163953Srrs  (gdb) p /r pass
73169352Srrs  $3 = (opt_pass *) 0x188b600
74170181Srrs
75163953SrrsBasic blocks are shown with their index in parentheses, apart from the
76163953SrrsCFG's entry and exit blocks, which are given as "ENTRY" and "EXIT":
77163953Srrs  (gdb) p bb
78168299Srrs  $9 = <basic_block 0x7ffff041f1a0 (2)>
79163953Srrs  (gdb) p cfun->cfg->x_entry_block_ptr
80170056Srrs  $10 = <basic_block 0x7ffff041f0d0 (ENTRY)>
81163953Srrs  (gdb) p cfun->cfg->x_exit_block_ptr
82163953Srrs  $11 = <basic_block 0x7ffff041f138 (EXIT)>
83169352Srrs
84169352SrrsCFG edges are shown with the src and dest blocks given in parentheses:
85169352Srrs  (gdb) p e
86169352Srrs  $1 = <edge 0x7ffff043f118 (ENTRY -> 6)>
87169352Srrs
88168709SrrsTree nodes are printed using Python code that emulates print_node_brief,
89170056Srrsrunning in gdb, rather than in the inferior:
90165647Srrs  (gdb) p cfun->decl
91170091Srrs  $1 = <function_decl 0x7ffff0420b00 foo>
92170091SrrsFor usability, the type is printed first (e.g. "function_decl"), rather
93170091Srrsthan just "tree".
94163953Srrs
95163953SrrsRTL expressions use a kludge: they are pretty-printed by injecting
96170056Srrscalls into print-rtl.c into the inferior:
97170056Srrs  Value returned is $1 = (note 9 8 10 [bb 3] NOTE_INSN_BASIC_BLOCK)
98163953Srrs  (gdb) p $1
99163953Srrs  $2 = (note 9 8 10 [bb 3] NOTE_INSN_BASIC_BLOCK)
100163953Srrs  (gdb) p /r $1
101163953Srrs  $3 = (rtx_def *) 0x7ffff043e140
102163953SrrsThis won't work for coredumps, and probably in other circumstances, but
103163953Srrsit's a quick way of getting lots of debuggability quickly.
104163953Srrs
105170859SrrsCallgraph nodes are printed with the name of the function decl, if
106170859Srrsavailable:
107163953Srrs  (gdb) frame 5
108170859Srrs  #5  0x00000000006c288a in expand_function (node=<cgraph_node* 0x7ffff0312720 "foo"/12345>) at ../../src/gcc/cgraphunit.c:1594
109163953Srrs  1594	  execute_pass_list (g->get_passes ()->all_passes);
110163953Srrs  (gdb) p node
111163953Srrs  $1 = <cgraph_node* 0x7ffff0312720 "foo"/12345>
112163953Srrs
113163953SrrsSimilarly for symtab_node and varpool_node classes.
114163953Srrs
115163953SrrsCgraph edges are printed with the name of caller and callee:
116163953Srrs    (gdb) p this->callees
117163953Srrs    $4 = <cgraph_edge* 0x7fffe25aa000 (<cgraph_node * 0x7fffe62b22e0 "_GLOBAL__sub_I__ZN5Pooma5pinfoE"/19660> -> <cgraph_node * 0x7fffe620f730 "__static_initialization_and_destruction_1"/19575>)>
118169420Srrs
119170056SrrsIPA reference follow very similar format:
120163953Srrs    (gdb) Value returned is $5 = <ipa_ref* 0x7fffefcb80c8 (<symtab_node * 0x7ffff562f000 "__dt_base "/875> -> <symtab_node * 0x7fffe795f000 "_ZTVN6Smarts8RunnableE"/16056>:IPA_REF_ADDR)>
121163953Srrs
122163953Srrsvec<> pointers are printed as the address followed by the elements in
123163953Srrsbraces.  Here's a length 2 vec:
124163953Srrs  (gdb) p bb->preds
125163953Srrs  $18 = 0x7ffff0428b68 = {<edge 0x7ffff044d380 (3 -> 5)>, <edge 0x7ffff044d3b8 (4 -> 5)>}
126163953Srrs
127163953Srrsand here's a length 1 vec:
128165647Srrs  (gdb) p bb->succs
129163953Srrs  $19 = 0x7ffff0428bb8 = {<edge 0x7ffff044d3f0 (5 -> EXIT)>}
130163953Srrs
131163953SrrsYou cannot yet use array notation [] to access the elements within the
132163953Srrsvector: attempting to do so instead gives you the vec itself (for vec[0]),
133163953Srrsor a (probably) invalid cast to vec<> for the memory after the vec (for
134163953Srrsvec[1] onwards).
135163953Srrs
136163953SrrsInstead (for now) you must access m_vecdata:
137163953Srrs  (gdb) p bb->preds->m_vecdata[0]
138163953Srrs  $20 = <edge 0x7ffff044d380 (3 -> 5)>
139163953Srrs  (gdb) p bb->preds->m_vecdata[1]
140163953Srrs  $21 = <edge 0x7ffff044d3b8 (4 -> 5)>
141163953Srrs"""
142163953Srrsimport os.path
143163953Srrsimport re
144163953Srrsimport sys
145163953Srrsimport tempfile
146169420Srrs
147169420Srrsimport gdb
148163953Srrsimport gdb.printing
149168299Srrsimport gdb.types
150163953Srrs
151163953Srrs# Convert "enum tree_code" (tree.def and tree.h) to a dict:
152163953Srrstree_code_dict = gdb.types.make_enum_dict(gdb.lookup_type('enum tree_code'))
153163953Srrs
154163953Srrs# ...and look up specific values for use later:
155163953SrrsIDENTIFIER_NODE = tree_code_dict['IDENTIFIER_NODE']
156163953SrrsTYPE_DECL = tree_code_dict['TYPE_DECL']
157163953SrrsSSA_NAME = tree_code_dict['SSA_NAME']
158163953Srrs
159163953Srrs# Similarly for "enum tree_code_class" (tree.h):
160163953Srrstree_code_class_dict = gdb.types.make_enum_dict(gdb.lookup_type('enum tree_code_class'))
161163953Srrstcc_type = tree_code_class_dict['tcc_type']
162165647Srrstcc_declaration = tree_code_class_dict['tcc_declaration']
163163953Srrs
164163953Srrs# Python3 has int() with arbitrary precision (bignum).  Python2 int() is 32-bit
165163953Srrs# on 32-bit hosts but remote targets may have 64-bit pointers there; Python2
166163953Srrs# long() is always 64-bit but Python3 no longer has anything named long.
167163953Srrsdef intptr(gdbval):
168163953Srrs    return long(gdbval) if sys.version_info.major == 2 else int(gdbval)
169163953Srrs
170168299Srrsclass Tree:
171163953Srrs    """
172163953Srrs    Wrapper around a gdb.Value for a tree, with various methods
173163953Srrs    corresponding to macros in gcc/tree.h
174163953Srrs    """
175163953Srrs    def __init__(self, gdbval):
176163953Srrs        self.gdbval = gdbval
177163953Srrs
178163953Srrs    def is_nonnull(self):
179163953Srrs        return intptr(self.gdbval)
180163953Srrs
181163953Srrs    def TREE_CODE(self):
182163953Srrs        """
183163953Srrs        Get gdb.Value corresponding to TREE_CODE (self)
184168299Srrs        as per:
185169420Srrs          #define TREE_CODE(NODE) ((enum tree_code) (NODE)->base.code)
186169420Srrs        """
187169420Srrs        return self.gdbval['base']['code']
188169420Srrs
189163953Srrs    def DECL_NAME(self):
190165220Srrs        """
191170181Srrs        Get Tree instance corresponding to DECL_NAME (self)
192165220Srrs        """
193165220Srrs        return Tree(self.gdbval['decl_minimal']['name'])
194165220Srrs
195165220Srrs    def TYPE_NAME(self):
196165220Srrs        """
197165220Srrs        Get Tree instance corresponding to result of TYPE_NAME (self)
198170181Srrs        """
199163953Srrs        return Tree(self.gdbval['type_common']['name'])
200163953Srrs
201163953Srrs    def IDENTIFIER_POINTER(self):
202163953Srrs        """
203163953Srrs        Get str correspoinding to result of IDENTIFIER_NODE (self)
204171167Sgnn        """
205163953Srrs        return self.gdbval['identifier']['id']['str'].string()
206163953Srrs
207163953Srrsclass TreePrinter:
208163996Srrs    "Prints a tree"
209163953Srrs
210163953Srrs    def __init__ (self, gdbval):
211163953Srrs        self.gdbval = gdbval
212163996Srrs        self.node = Tree(gdbval)
213171167Sgnn
214163953Srrs    def to_string (self):
215163953Srrs        # like gcc/print-tree.c:print_node_brief
216163953Srrs        # #define TREE_CODE(NODE) ((enum tree_code) (NODE)->base.code)
217163953Srrs        # tree_code_name[(int) TREE_CODE (node)])
218163953Srrs        if intptr(self.gdbval) == 0:
219163953Srrs            return '<tree 0x0>'
220165647Srrs
221165647Srrs        val_TREE_CODE = self.node.TREE_CODE()
222165647Srrs
223165647Srrs        # extern const enum tree_code_class tree_code_type[];
224169655Srrs        # #define TREE_CODE_CLASS(CODE)	tree_code_type[(int) (CODE)]
225169378Srrs
226170181Srrs        if val_TREE_CODE == 0xa5a5:
227163953Srrs            return '<ggc_freed 0x%x>' % intptr(self.gdbval)
228163953Srrs
229163953Srrs        val_tree_code_type = gdb.parse_and_eval('tree_code_type')
230169352Srrs        val_tclass = val_tree_code_type[val_TREE_CODE]
231163953Srrs
232163953Srrs        val_tree_code_name = gdb.parse_and_eval('tree_code_name')
233163953Srrs        val_code_name = val_tree_code_name[intptr(val_TREE_CODE)]
234163953Srrs        #print(val_code_name.string())
235163953Srrs
236163953Srrs        try:
237163953Srrs            result = '<%s 0x%x' % (val_code_name.string(), intptr(self.gdbval))
238163953Srrs        except:
239163953Srrs            return '<tree 0x%x>' % intptr(self.gdbval)
240169420Srrs        if intptr(val_tclass) == tcc_declaration:
241163953Srrs            tree_DECL_NAME = self.node.DECL_NAME()
242169420Srrs            if tree_DECL_NAME.is_nonnull():
243163953Srrs                 result += ' %s' % tree_DECL_NAME.IDENTIFIER_POINTER()
244163953Srrs            else:
245163953Srrs                pass # TODO: labels etc
246163953Srrs        elif intptr(val_tclass) == tcc_type:
247163953Srrs            tree_TYPE_NAME = Tree(self.gdbval['type_common']['name'])
248163953Srrs            if tree_TYPE_NAME.is_nonnull():
249163953Srrs                if tree_TYPE_NAME.TREE_CODE() == IDENTIFIER_NODE:
250169352Srrs                    result += ' %s' % tree_TYPE_NAME.IDENTIFIER_POINTER()
251163953Srrs                elif tree_TYPE_NAME.TREE_CODE() == TYPE_DECL:
252163953Srrs                    if tree_TYPE_NAME.DECL_NAME().is_nonnull():
253163953Srrs                        result += ' %s' % tree_TYPE_NAME.DECL_NAME().IDENTIFIER_POINTER()
254163953Srrs        if self.node.TREE_CODE() == IDENTIFIER_NODE:
255163953Srrs            result += ' %s' % self.node.IDENTIFIER_POINTER()
256171259Sdelphij        elif self.node.TREE_CODE() == SSA_NAME:
257171259Sdelphij            result += ' %u' % self.gdbval['base']['u']['version']
258163953Srrs        # etc
259168299Srrs        result += '>'
260163953Srrs        return result
261163953Srrs
262163953Srrs######################################################################
263163953Srrs# Callgraph pretty-printers
264163953Srrs######################################################################
265163953Srrs
266163953Srrsclass SymtabNodePrinter:
267163953Srrs    def __init__(self, gdbval):
268163953Srrs        self.gdbval = gdbval
269163953Srrs
270163953Srrs    def to_string (self):
271163953Srrs        t = str(self.gdbval.type)
272163953Srrs        result = '<%s 0x%x' % (t, intptr(self.gdbval))
273163953Srrs        if intptr(self.gdbval):
274163953Srrs            # symtab_node::name calls lang_hooks.decl_printable_name
275163953Srrs            # default implementation (lhd_decl_printable_name) is:
276163953Srrs            #    return IDENTIFIER_POINTER (DECL_NAME (decl));
277163953Srrs            tree_decl = Tree(self.gdbval['decl'])
278163953Srrs            result += ' "%s"/%d' % (tree_decl.DECL_NAME().IDENTIFIER_POINTER(), self.gdbval['order'])
279163953Srrs        result += '>'
280163953Srrs        return result
281165220Srrs
282163953Srrsclass CgraphEdgePrinter:
283163953Srrs    def __init__(self, gdbval):
284163953Srrs        self.gdbval = gdbval
285163953Srrs
286163953Srrs    def to_string (self):
287163953Srrs        result = '<cgraph_edge* 0x%x' % intptr(self.gdbval)
288163953Srrs        if intptr(self.gdbval):
289163953Srrs            src = SymtabNodePrinter(self.gdbval['caller']).to_string()
290163953Srrs            dest = SymtabNodePrinter(self.gdbval['callee']).to_string()
291163953Srrs            result += ' (%s -> %s)' % (src, dest)
292163953Srrs        result += '>'
293163953Srrs        return result
294163953Srrs
295163953Srrsclass IpaReferencePrinter:
296168299Srrs    def __init__(self, gdbval):
297163953Srrs        self.gdbval = gdbval
298163953Srrs
299163953Srrs    def to_string (self):
300163953Srrs        result = '<ipa_ref* 0x%x' % intptr(self.gdbval)
301168299Srrs        if intptr(self.gdbval):
302163953Srrs            src = SymtabNodePrinter(self.gdbval['referring']).to_string()
303163953Srrs            dest = SymtabNodePrinter(self.gdbval['referred']).to_string()
304163953Srrs            result += ' (%s -> %s:%s)' % (src, dest, str(self.gdbval['use']))
305163953Srrs        result += '>'
306163953Srrs        return result
307163953Srrs
308163953Srrs######################################################################
309163953Srrs# Dwarf DIE pretty-printers
310163953Srrs######################################################################
311163953Srrs
312163953Srrsclass DWDieRefPrinter:
313163953Srrs    def __init__(self, gdbval):
314163953Srrs        self.gdbval = gdbval
315163953Srrs
316163953Srrs    def to_string (self):
317163953Srrs        if intptr(self.gdbval) == 0:
318163953Srrs            return '<dw_die_ref 0x0>'
319163953Srrs        result = '<dw_die_ref 0x%x' % intptr(self.gdbval)
320163953Srrs        result += ' %s' % self.gdbval['die_tag']
321163953Srrs        if intptr(self.gdbval['die_parent']) != 0:
322163953Srrs            result += ' <parent=0x%x %s>' % (intptr(self.gdbval['die_parent']),
323169420Srrs                                             self.gdbval['die_parent']['die_tag'])
324163953Srrs
325169420Srrs        result += '>'
326163953Srrs        return result
327163953Srrs
328163953Srrs######################################################################
329163953Srrs
330171259Sdelphijclass GimplePrinter:
331163953Srrs    def __init__(self, gdbval):
332163953Srrs        self.gdbval = gdbval
333163953Srrs
334167598Srrs    def to_string (self):
335166086Srrs        if intptr(self.gdbval) == 0:
336163953Srrs            return '<gimple 0x0>'
337167598Srrs        val_gimple_code = self.gdbval['code']
338167598Srrs        val_gimple_code_name = gdb.parse_and_eval('gimple_code_name')
339163953Srrs        val_code_name = val_gimple_code_name[intptr(val_gimple_code)]
340163953Srrs        result = '<%s 0x%x' % (val_code_name.string(),
341163953Srrs                               intptr(self.gdbval))
342163953Srrs        result += '>'
343163953Srrs        return result
344163953Srrs
345163953Srrs######################################################################
346163953Srrs# CFG pretty-printers
347163953Srrs######################################################################
348163953Srrs
349163953Srrsdef bb_index_to_str(index):
350163953Srrs    if index == 0:
351163953Srrs        return 'ENTRY'
352163953Srrs    elif index == 1:
353163953Srrs        return 'EXIT'
354163953Srrs    else:
355163953Srrs        return '%i' % index
356163953Srrs
357163953Srrsclass BasicBlockPrinter:
358163953Srrs    def __init__(self, gdbval):
359163953Srrs        self.gdbval = gdbval
360163953Srrs
361163953Srrs    def to_string (self):
362163953Srrs        result = '<basic_block 0x%x' % intptr(self.gdbval)
363163953Srrs        if intptr(self.gdbval):
364163953Srrs            result += ' (%s)' % bb_index_to_str(intptr(self.gdbval['index']))
365163953Srrs        result += '>'
366163953Srrs        return result
367163953Srrs
368165647Srrsclass CfgEdgePrinter:
369163953Srrs    def __init__(self, gdbval):
370163953Srrs        self.gdbval = gdbval
371163953Srrs
372163953Srrs    def to_string (self):
373163953Srrs        result = '<edge 0x%x' % intptr(self.gdbval)
374163953Srrs        if intptr(self.gdbval):
375163953Srrs            src = bb_index_to_str(intptr(self.gdbval['src']['index']))
376163953Srrs            dest = bb_index_to_str(intptr(self.gdbval['dest']['index']))
377163953Srrs            result += ' (%s -> %s)' % (src, dest)
378163953Srrs        result += '>'
379163953Srrs        return result
380163953Srrs
381163953Srrs######################################################################
382163953Srrs
383163953Srrsclass Rtx:
384167598Srrs    def __init__(self, gdbval):
385163953Srrs        self.gdbval = gdbval
386163953Srrs
387163953Srrs    def GET_CODE(self):
388163953Srrs        return self.gdbval['code']
389163953Srrs
390163953Srrsdef GET_RTX_LENGTH(code):
391163953Srrs    val_rtx_length = gdb.parse_and_eval('rtx_length')
392163953Srrs    return intptr(val_rtx_length[code])
393163953Srrs
394163953Srrsdef GET_RTX_NAME(code):
395163953Srrs    val_rtx_name = gdb.parse_and_eval('rtx_name')
396163953Srrs    return val_rtx_name[code].string()
397163953Srrs
398163953Srrsdef GET_RTX_FORMAT(code):
399163953Srrs    val_rtx_format = gdb.parse_and_eval('rtx_format')
400163953Srrs    return val_rtx_format[code].string()
401163953Srrs
402163953Srrsclass RtxPrinter:
403163953Srrs    def __init__(self, gdbval):
404163953Srrs        self.gdbval = gdbval
405163953Srrs        self.rtx = Rtx(gdbval)
406163953Srrs
407163953Srrs    def to_string (self):
408163953Srrs        """
409163953Srrs        For now, a cheap kludge: invoke the inferior's print
410163953Srrs        function to get a string to use the user, and return an empty
411163953Srrs        string for gdb
412163953Srrs        """
413163953Srrs        # We use print_inline_rtx to avoid a trailing newline
414163953Srrs        gdb.execute('call print_inline_rtx (stderr, (const_rtx) %s, 0)'
415163953Srrs                    % intptr(self.gdbval))
416163953Srrs        return ''
417163953Srrs
418163953Srrs        # or by hand; based on gcc/print-rtl.c:print_rtx
419163953Srrs        result = ('<rtx_def 0x%x'
420163953Srrs                  % (intptr(self.gdbval)))
421163953Srrs        code = self.rtx.GET_CODE()
422163953Srrs        result += ' (%s' % GET_RTX_NAME(code)
423163953Srrs        format_ = GET_RTX_FORMAT(code)
424163953Srrs        for i in range(GET_RTX_LENGTH(code)):
425163953Srrs            print(format_[i])
426163953Srrs        result += ')>'
427163953Srrs        return result
428163953Srrs
429164085Srrs######################################################################
430163953Srrs
431163953Srrsclass PassPrinter:
432163953Srrs    def __init__(self, gdbval):
433163953Srrs        self.gdbval = gdbval
434164085Srrs
435167598Srrs    def to_string (self):
436163953Srrs        result = '<opt_pass* 0x%x' % intptr(self.gdbval)
437167598Srrs        if intptr(self.gdbval):
438167598Srrs            result += (' "%s"(%i)'
439170587Srwatson                       % (self.gdbval['name'].string(),
440163953Srrs                          intptr(self.gdbval['static_pass_number'])))
441163953Srrs        result += '>'
442163953Srrs        return result
443163953Srrs
444163953Srrs######################################################################
445163953Srrs
446163953Srrsclass VecPrinter:
447163953Srrs    #    -ex "up" -ex "p bb->preds"
448163953Srrs    def __init__(self, gdbval):
449163953Srrs        self.gdbval = gdbval
450163953Srrs
451163953Srrs    def display_hint (self):
452163953Srrs        return 'array'
453167598Srrs
454163953Srrs    def to_string (self):
455164085Srrs        # A trivial implementation; prettyprinting the contents is done
456164085Srrs        # by gdb calling the "children" method below.
457163953Srrs        return '0x%x' % intptr(self.gdbval)
458163953Srrs
459164085Srrs    def children (self):
460163953Srrs        if intptr(self.gdbval) == 0:
461164085Srrs            return
462163953Srrs        m_vecpfx = self.gdbval['m_vecpfx']
463163953Srrs        m_num = m_vecpfx['m_num']
464163953Srrs        m_vecdata = self.gdbval['m_vecdata']
465164085Srrs        for i in range(m_num):
466164085Srrs            yield ('[%d]' % i, m_vecdata[i])
467164085Srrs
468164085Srrs######################################################################
469164085Srrs
470164085Srrsclass MachineModePrinter:
471164085Srrs    def __init__(self, gdbval):
472164085Srrs        self.gdbval = gdbval
473164085Srrs
474164085Srrs    def to_string (self):
475164085Srrs        name = str(self.gdbval['m_mode'])
476164085Srrs        return name[2:] if name.startswith('E_') else name
477164085Srrs
478164085Srrs######################################################################
479164085Srrs
480164085Srrsclass OptMachineModePrinter:
481163953Srrs    def __init__(self, gdbval):
482163953Srrs        self.gdbval = gdbval
483163953Srrs
484163953Srrs    def to_string (self):
485163953Srrs        name = str(self.gdbval['m_mode'])
486163953Srrs        if name == 'E_VOIDmode':
487163953Srrs            return '<None>'
488163953Srrs        return name[2:] if name.startswith('E_') else name
489163953Srrs
490163953Srrs######################################################################
491163953Srrs
492163953Srrs# TODO:
493163953Srrs#   * hashtab
494163953Srrs#   * location_t
495163953Srrs
496163953Srrsclass GdbSubprinter(gdb.printing.SubPrettyPrinter):
497163953Srrs    def __init__(self, name, class_):
498163953Srrs        super(GdbSubprinter, self).__init__(name)
499163953Srrs        self.class_ = class_
500163953Srrs
501163953Srrs    def handles_type(self, str_type):
502163953Srrs        raise NotImplementedError
503163953Srrs
504163953Srrsclass GdbSubprinterTypeList(GdbSubprinter):
505163953Srrs    """
506163953Srrs    A GdbSubprinter that handles a specific set of types
507163953Srrs    """
508163953Srrs    def __init__(self, str_types, name, class_):
509163953Srrs        super(GdbSubprinterTypeList, self).__init__(name, class_)
510169380Srrs        self.str_types = frozenset(str_types)
511169380Srrs
512163953Srrs    def handles_type(self, str_type):
513167695Srrs        return str_type in self.str_types
514163953Srrs
515163953Srrsclass GdbSubprinterRegex(GdbSubprinter):
516163953Srrs    """
517163953Srrs    A GdbSubprinter that handles types that match a regex
518167695Srrs    """
519167695Srrs    def __init__(self, regex, name, class_):
520163953Srrs        super(GdbSubprinterRegex, self).__init__(name, class_)
521163953Srrs        self.regex = re.compile(regex)
522163953Srrs
523163953Srrs    def handles_type(self, str_type):
524163953Srrs        return self.regex.match(str_type)
525163953Srrs
526163953Srrsclass GdbPrettyPrinters(gdb.printing.PrettyPrinter):
527163953Srrs    def __init__(self, name):
528163953Srrs        super(GdbPrettyPrinters, self).__init__(name, [])
529163953Srrs
530163953Srrs    def add_printer_for_types(self, types, name, class_):
531163953Srrs        self.subprinters.append(GdbSubprinterTypeList(types, name, class_))
532163953Srrs
533163953Srrs    def add_printer_for_regex(self, regex, name, class_):
534163953Srrs        self.subprinters.append(GdbSubprinterRegex(regex, name, class_))
535166086Srrs
536163953Srrs    def __call__(self, gdbval):
537170205Srrs        type_ = gdbval.type.unqualified()
538163953Srrs        str_type = str(type_)
539163953Srrs        for printer in self.subprinters:
540163953Srrs            if printer.enabled and printer.handles_type(str_type):
541163953Srrs                return printer.class_(gdbval)
542163953Srrs
543163953Srrs        # Couldn't find a pretty printer (or it was disabled):
544167695Srrs        return None
545163953Srrs
546163953Srrs
547163953Srrsdef build_pretty_printer():
548170205Srrs    pp = GdbPrettyPrinters('gcc')
549163953Srrs    pp.add_printer_for_types(['tree', 'const_tree'],
550163953Srrs                             'tree', TreePrinter)
551163953Srrs    pp.add_printer_for_types(['cgraph_node *', 'varpool_node *', 'symtab_node *'],
552170205Srrs                             'symtab_node', SymtabNodePrinter)
553163953Srrs    pp.add_printer_for_types(['cgraph_edge *'],
554163953Srrs                             'cgraph_edge', CgraphEdgePrinter)
555163953Srrs    pp.add_printer_for_types(['ipa_ref *'],
556163953Srrs                             'ipa_ref', IpaReferencePrinter)
557163953Srrs    pp.add_printer_for_types(['dw_die_ref'],
558163953Srrs                             'dw_die_ref', DWDieRefPrinter)
559163953Srrs    pp.add_printer_for_types(['gimple', 'gimple *',
560163953Srrs
561163953Srrs                              # Keep this in the same order as gimple.def:
562163953Srrs                              'gimple_cond', 'const_gimple_cond',
563163953Srrs                              'gimple_statement_cond *',
564163953Srrs                              'gimple_debug', 'const_gimple_debug',
565163953Srrs                              'gimple_statement_debug *',
566163953Srrs                              'gimple_label', 'const_gimple_label',
567163953Srrs                              'gimple_statement_label *',
568163953Srrs                              'gimple_switch', 'const_gimple_switch',
569163953Srrs                              'gimple_statement_switch *',
570163953Srrs                              'gimple_assign', 'const_gimple_assign',
571170205Srrs                              'gimple_statement_assign *',
572163953Srrs                              'gimple_bind', 'const_gimple_bind',
573163953Srrs                              'gimple_statement_bind *',
574163953Srrs                              'gimple_phi', 'const_gimple_phi',
575163953Srrs                              'gimple_statement_phi *'],
576163953Srrs
577163953Srrs                             'gimple',
578163953Srrs                             GimplePrinter)
579163953Srrs    pp.add_printer_for_types(['basic_block', 'basic_block_def *'],
580166086Srrs                             'basic_block',
581163953Srrs                             BasicBlockPrinter)
582163953Srrs    pp.add_printer_for_types(['edge', 'edge_def *'],
583163953Srrs                             'edge',
584163953Srrs                             CfgEdgePrinter)
585163953Srrs    pp.add_printer_for_types(['rtx_def *'], 'rtx_def', RtxPrinter)
586170056Srrs    pp.add_printer_for_types(['opt_pass *'], 'opt_pass', PassPrinter)
587170056Srrs
588170056Srrs    pp.add_printer_for_regex(r'vec<(\S+), (\S+), (\S+)> \*',
589170056Srrs                             'vec',
590170056Srrs                             VecPrinter)
591170056Srrs
592170056Srrs    pp.add_printer_for_regex(r'opt_mode<(\S+)>',
593170056Srrs                             'opt_mode', OptMachineModePrinter)
594170056Srrs    pp.add_printer_for_types(['opt_scalar_int_mode',
595170056Srrs                              'opt_scalar_float_mode',
596163953Srrs                              'opt_scalar_mode'],
597163953Srrs                             'opt_mode', OptMachineModePrinter)
598163953Srrs    pp.add_printer_for_regex(r'pod_mode<(\S+)>',
599166023Srrs                             'pod_mode', MachineModePrinter)
600163953Srrs    pp.add_printer_for_types(['scalar_int_mode_pod',
601163953Srrs                              'scalar_mode_pod'],
602163953Srrs                             'pod_mode', MachineModePrinter)
603163953Srrs    for mode in ('scalar_mode', 'scalar_int_mode', 'scalar_float_mode',
604163953Srrs                 'complex_mode'):
605163953Srrs        pp.add_printer_for_types([mode], mode, MachineModePrinter)
606163953Srrs
607163953Srrs    return pp
608163953Srrs
609163953Srrsgdb.printing.register_pretty_printer(
610163953Srrs    gdb.current_objfile(),
611163953Srrs    build_pretty_printer(),
612163953Srrs    replace=True)
613163953Srrs
614163953Srrsdef find_gcc_source_dir():
615163953Srrs    # Use location of global "g" to locate the source tree
616163953Srrs    sym_g = gdb.lookup_global_symbol('g')
617170744Srrs    path = sym_g.symtab.filename # e.g. '../../src/gcc/context.h'
618163953Srrs    srcdir = os.path.split(path)[0] # e.g. '../../src/gcc'
619163953Srrs    return srcdir
620163953Srrs
621163953Srrsclass PassNames:
622163953Srrs    """Parse passes.def, gathering a list of pass class names"""
623163953Srrs    def __init__(self):
624163953Srrs        srcdir = find_gcc_source_dir()
625163953Srrs        self.names = []
626163953Srrs        with open(os.path.join(srcdir, 'passes.def')) as f:
627163953Srrs            for line in f:
628163953Srrs                m = re.match('\s*NEXT_PASS \(([^,]+).*\);', line)
629163953Srrs                if m:
630163953Srrs                    self.names.append(m.group(1))
631163953Srrs
632163953Srrsclass BreakOnPass(gdb.Command):
633163953Srrs    """
634163953Srrs    A custom command for putting breakpoints on the execute hook of passes.
635163953Srrs    This is largely a workaround for issues with tab-completion in gdb when
636163953Srrs    setting breakpoints on methods on classes within anonymous namespaces.
637170744Srrs
638163953Srrs    Example of use: putting a breakpoint on "final"
639163953Srrs      (gdb) break-on-pass
640163953Srrs    Press <TAB>; it autocompletes to "pass_":
641163953Srrs      (gdb) break-on-pass pass_
642163953Srrs    Press <TAB>:
643163953Srrs      Display all 219 possibilities? (y or n)
644163953Srrs    Press "n"; then type "f":
645163953Srrs      (gdb) break-on-pass pass_f
646163953Srrs    Press <TAB> to autocomplete to pass classnames beginning with "pass_f":
647163953Srrs      pass_fast_rtl_dce              pass_fold_builtins
648163953Srrs      pass_feedback_split_functions  pass_forwprop
649163953Srrs      pass_final                     pass_fre
650163953Srrs      pass_fixup_cfg                 pass_free_cfg
651163953Srrs    Type "in<TAB>" to complete to "pass_final":
652163953Srrs      (gdb) break-on-pass pass_final
653163953Srrs    ...and hit <RETURN>:
654163953Srrs      Breakpoint 6 at 0x8396ba: file ../../src/gcc/final.c, line 4526.
655163953Srrs    ...and we have a breakpoint set; continue execution:
656163953Srrs      (gdb) cont
657163953Srrs      Continuing.
658163953Srrs      Breakpoint 6, (anonymous namespace)::pass_final::execute (this=0x17fb990) at ../../src/gcc/final.c:4526
659163953Srrs      4526	  virtual unsigned int execute (function *) { return rest_of_handle_final (); }
660163953Srrs    """
661163953Srrs    def __init__(self):
662163953Srrs        gdb.Command.__init__(self, 'break-on-pass', gdb.COMMAND_BREAKPOINTS)
663163953Srrs        self.pass_names = None
664163953Srrs
665163953Srrs    def complete(self, text, word):
666163953Srrs        # Lazily load pass names:
667169380Srrs        if not self.pass_names:
668169380Srrs            self.pass_names = PassNames()
669163953Srrs
670163953Srrs        return [name
671163953Srrs                for name in sorted(self.pass_names.names)
672163953Srrs                if name.startswith(text)]
673169380Srrs
674169380Srrs    def invoke(self, arg, from_tty):
675163953Srrs        sym = '(anonymous namespace)::%s::execute' % arg
676163953Srrs        breakpoint = gdb.Breakpoint(sym)
677163953Srrs
678163953SrrsBreakOnPass()
679163953Srrs
680163953Srrsclass DumpFn(gdb.Command):
681167695Srrs    """
682163953Srrs    A custom command to dump a gimple/rtl function to file.  By default, it
683163953Srrs    dumps the current function using 0 as dump_flags, but the function and flags
684163953Srrs    can also be specified. If /f <file> are passed as the first two arguments,
685163953Srrs    the dump is written to that file.  Otherwise, a temporary file is created
686167695Srrs    and opened in the text editor specified in the EDITOR environment variable.
687167695Srrs
688163953Srrs    Examples of use:
689163953Srrs      (gdb) dump-fn
690163953Srrs      (gdb) dump-fn /f foo.1.txt
691163953Srrs      (gdb) dump-fn cfun->decl
692163953Srrs      (gdb) dump-fn /f foo.1.txt cfun->decl
693163953Srrs      (gdb) dump-fn cfun->decl 0
694163953Srrs      (gdb) dump-fn cfun->decl dump_flags
695163953Srrs    """
696163953Srrs
697163953Srrs    def __init__(self):
698163953Srrs        gdb.Command.__init__(self, 'dump-fn', gdb.COMMAND_USER)
699163953Srrs
700167598Srrs    def invoke(self, arg, from_tty):
701163953Srrs        # Parse args, check number of args
702168709Srrs        args = gdb.string_to_argv(arg)
703168709Srrs        if len(args) >= 1 and args[0] == "/f":
704163953Srrs            if len(args) == 1:
705163953Srrs                print ("Missing file argument")
706163953Srrs                return
707163953Srrs            filename = args[1]
708163953Srrs            editor_mode = False
709163953Srrs            base_arg = 2
710163953Srrs        else:
711163953Srrs            editor = os.getenv("EDITOR", "")
712163953Srrs            if editor == "":
713163953Srrs                print ("EDITOR environment variable not defined")
714166675Srrs                return
715163953Srrs            editor_mode = True
716163953Srrs            base_arg = 0
717163953Srrs        if len(args) - base_arg > 2:
718163953Srrs            print ("Too many arguments")
719163953Srrs            return
720163953Srrs
721163953Srrs        # Set func
722163953Srrs        if len(args) - base_arg >= 1:
723163953Srrs            funcname = args[base_arg]
724163953Srrs            printfuncname = "function %s" % funcname
725163953Srrs        else:
726163953Srrs            funcname = "cfun ? cfun->decl : current_function_decl"
727163953Srrs            printfuncname = "current function"
728163953Srrs        func = gdb.parse_and_eval(funcname)
729163953Srrs        if func == 0:
730163953Srrs            print ("Could not find %s" % printfuncname)
731163953Srrs            return
732163953Srrs        func = "(tree)%u" % func
733163953Srrs
734163953Srrs        # Set flags
735163953Srrs        if len(args) - base_arg >= 2:
736168709Srrs            flags = gdb.parse_and_eval(args[base_arg + 1])
737163953Srrs        else:
738168709Srrs            flags = 0
739168709Srrs
740163953Srrs        # Get tempory file, if necessary
741163953Srrs        if editor_mode:
742163953Srrs            f = tempfile.NamedTemporaryFile(delete=False, suffix=".txt")
743163953Srrs            filename = f.name
744163953Srrs            f.close()
745163953Srrs
746163953Srrs        # Open file
747165220Srrs        fp = gdb.parse_and_eval("(FILE *) fopen (\"%s\", \"w\")" % filename)
748165220Srrs        if fp == 0:
749163953Srrs            print ("Could not open file: %s" % filename)
750163953Srrs            return
751163953Srrs
752163953Srrs        # Dump function to file
753163953Srrs        _ = gdb.parse_and_eval("dump_function_to_file (%s, %s, %u)" %
754163953Srrs                               (func, fp, flags))
755163953Srrs
756163953Srrs        # Close file
757163953Srrs        ret = gdb.parse_and_eval("(int) fclose (%s)" % fp)
758163953Srrs        if ret != 0:
759163953Srrs            print ("Could not close file: %s" % filename)
760163953Srrs            return
761163953Srrs
762163953Srrs        # Open file in editor, if necessary
763163953Srrs        if editor_mode:
764163953Srrs            os.system("( %s \"%s\"; rm \"%s\" ) &" %
765163953Srrs                      (editor, filename, filename))
766163953Srrs
767163953SrrsDumpFn()
768163953Srrs
769163953Srrsclass DotFn(gdb.Command):
770163953Srrs    """
771163953Srrs    A custom command to show a gimple/rtl function control flow graph.
772163953Srrs    By default, it show the current function, but the function can also be
773163953Srrs    specified.
774163953Srrs
775166675Srrs    Examples of use:
776166675Srrs      (gdb) dot-fn
777166675Srrs      (gdb) dot-fn cfun
778166675Srrs      (gdb) dot-fn cfun 0
779163953Srrs      (gdb) dot-fn cfun dump_flags
780163953Srrs    """
781163953Srrs    def __init__(self):
782163953Srrs        gdb.Command.__init__(self, 'dot-fn', gdb.COMMAND_USER)
783163953Srrs
784163953Srrs    def invoke(self, arg, from_tty):
785163953Srrs        # Parse args, check number of args
786163953Srrs        args = gdb.string_to_argv(arg)
787163953Srrs        if len(args) > 2:
788163953Srrs            print("Too many arguments")
789163953Srrs            return
790163953Srrs
791163953Srrs        # Set func
792163953Srrs        if len(args) >= 1:
793163953Srrs            funcname = args[0]
794163953Srrs            printfuncname = "function %s" % funcname
795163953Srrs        else:
796163953Srrs            funcname = "cfun"
797163953Srrs            printfuncname = "current function"
798163953Srrs        func = gdb.parse_and_eval(funcname)
799163953Srrs        if func == 0:
800163953Srrs            print("Could not find %s" % printfuncname)
801163953Srrs            return
802163953Srrs        func = "(struct function *)%s" % func
803163953Srrs
804163953Srrs        # Set flags
805163953Srrs        if len(args) >= 2:
806163953Srrs            flags = gdb.parse_and_eval(args[1])
807163953Srrs        else:
808163953Srrs            flags = 0
809163953Srrs
810163953Srrs        # Get temp file
811168709Srrs        f = tempfile.NamedTemporaryFile(delete=False)
812163953Srrs        filename = f.name
813163953Srrs
814163953Srrs        # Close and reopen temp file to get C FILE*
815163953Srrs        f.close()
816163953Srrs        fp = gdb.parse_and_eval("(FILE *) fopen (\"%s\", \"w\")" % filename)
817163953Srrs        if fp == 0:
818163953Srrs            print("Cannot open temp file")
819163953Srrs            return
820163953Srrs
821163953Srrs        # Write graph to temp file
822163953Srrs        _ = gdb.parse_and_eval("start_graph_dump (%s, \"<debug>\")" % fp)
823163953Srrs        _ = gdb.parse_and_eval("print_graph_cfg (%s, %s, %u)"
824163953Srrs                               % (fp, func, flags))
825163953Srrs        _ = gdb.parse_and_eval("end_graph_dump (%s)" % fp)
826163953Srrs
827163953Srrs        # Close temp file
828163953Srrs        ret = gdb.parse_and_eval("(int) fclose (%s)" % fp)
829163953Srrs        if ret != 0:
830163953Srrs            print("Could not close temp file: %s" % filename)
831163953Srrs            return
832163953Srrs
833163953Srrs        # Show graph in temp file
834169352Srrs        os.system("( dot -Tx11 \"%s\"; rm \"%s\" ) &" % (filename, filename))
835163953Srrs
836163953SrrsDotFn()
837169352Srrs
838163953Srrsprint('Successfully loaded GDB hooks for GCC')
839163953Srrs