Loading [MathJax]/extensions/tex2jax.js
ATLAS Offline Software
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
pahole.py
Go to the documentation of this file.
1 # noqa: ATL902
2 # origin: https://github.com/PhilArmstrong/pahole-gdb
3 #
4 # File: GdbUtils/python/pahole.py
5 #
6 # pahole command for gdb
7 
8 # Copyright (C) 2008, 2025 Free Software Foundation, Inc.
9 
10 # This program is free software; you can redistribute it and/or modify
11 # it under the terms of the GNU General Public License as published by
12 # the Free Software Foundation; either version 3 of the License, or
13 # (at your option) any later version.
14 #
15 # This program is distributed in the hope that it will be useful,
16 # but WITHOUT ANY WARRANTY; without even the implied warranty of
17 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 # GNU General Public License for more details.
19 #
20 # You should have received a copy of the GNU General Public License
21 # along with this program. If not, see <http://www.gnu.org/licenses/>.
22 
23 import gdb
24 import gdb.types
25 import math
26 
27 class Pahole (gdb.Command):
28  """Show the holes in a structure.
29 This command takes a single argument, a type name.
30 It prints the type and displays comments showing where holes are."""
31 
32  def __init__ (self):
33  super (Pahole, self).__init__ ("pahole", gdb.COMMAND_DATA,
34  gdb.COMPLETE_SYMBOL)
35 
36  def pahole (self, atype, level, name, walk=False, nested=False):
37  if name is None:
38  name = ''
39  tag = atype.tag
40  if tag is None:
41  tag = ''
42  kind = 'struct' if atype.code == gdb.TYPE_CODE_STRUCT else 'union'
43  if not nested:
44  print ('/* %4d 0x%04x */ ' % (atype.sizeof, atype.sizeof), end="")
45  print ('%s%s %s {' % ( ' ' * (2 * level), kind, tag))
46  endpos = 0
47  for field in atype.fields():
48  # Skip static fields
49  if not hasattr (field, ('bitpos')):
50  continue
51  # find the type
52  ftype = field.type.strip_typedefs()
53 
54  # Detect hole
55  if endpos < field.bitpos:
56  hole = field.bitpos - endpos
57  print ('/* XXX %4d */ !!' % (hole // 8), end="")
58  print (' ' * (4 + 2 * level - 2), end="")
59  print ('char [%d] __%d_bit_padding__' % (math.ceil(hole / 8), hole))
60 
61  # Are we a bitfield?
62  if field.bitsize > 0:
63  fieldsize = field.bitsize
64  else:
65  if (ftype.code == gdb.TYPE_CODE_STRUCT or ftype.code == gdb.TYPE_CODE_UNION) and len(ftype.fields()) == 0:
66  fieldsize = 0 # empty struct
67  else:
68  fieldsize = 8 * ftype.sizeof # will get packing wrong for structs
69 
70  print ('/* %3d 0x%03x %4d */ ' % (field.bitpos // 8, field.bitpos // 8, fieldsize // 8), end="")
71  endpos = field.bitpos + fieldsize
72 
73  # Walk nested structure or print variable size (this is not a hole)
74  if walk and (ftype.code == gdb.TYPE_CODE_STRUCT or ftype.code == gdb.TYPE_CODE_UNION):
75  print (' ', end="")
76  self.pahole (ftype, level + 1, field.name, walk=walk, nested=True)
77  else:
78  print (' ' * (4 + 2 * level), end="")
79  print ('%s %s' % (str (ftype), field.name),end="")
80  # Append bitfield size if non-standard
81  if fieldsize != ftype.sizeof * 8:
82  print (':%d' % fieldsize)
83  else:
84  print ('')
85 
86  # Check for padding at the end
87  if endpos // 8 < atype.sizeof:
88  hole = 8 * atype.sizeof - endpos
89  print ('/* XXX %4d */ !!' % hole, end="")
90  print (' ' * (4 + 2 * level - 2), end="")
91  print ('char [%d] __%d_bit_padding__' % (math.ceil(hole / 8), hole))
92 
93  print (' ' * (14 + 2 * level), end="")
94  print (' } %s' % name)
95 
96  def invoke (self, arg, from_tty):
97  argv = gdb.string_to_argv(arg)
98  if len(argv) > 2:
99  raise gdb.GdbError('pahole takes a type name and an optional "walk" argument.')
100  stype = gdb.lookup_type (argv[0])
101  ptype = stype.strip_typedefs()
102  if ptype.code != gdb.TYPE_CODE_STRUCT and ptype.code != gdb.TYPE_CODE_UNION:
103  raise gdb.GdbError('%s is not a struct/union type: %s' % (arg, ptype.code))
104 
105  # Should the entire object be walked recursively?
106  walk = len(argv) > 1 and argv[1] == "walk"
107 
108  self.pahole (ptype, 0, argv[0], walk=walk)
109 
110 Pahole()
python.pahole.Pahole.__init__
def __init__(self)
Definition: pahole.py:32
python.pahole.Pahole.invoke
def invoke(self, arg, from_tty)
Definition: pahole.py:96
python.pahole.Pahole
Definition: pahole.py:27
python.pahole.Pahole.pahole
def pahole(self, atype, level, name, walk=False, nested=False)
Definition: pahole.py:36