printers.py 66 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797
  1. # Pretty-printers for libstdc++.
  2. # Copyright (C) 2008-2018 Free Software Foundation, Inc.
  3. # This program is free software; you can redistribute it and/or modify
  4. # it under the terms of the GNU General Public License as published by
  5. # the Free Software Foundation; either version 3 of the License, or
  6. # (at your option) any later version.
  7. #
  8. # This program is distributed in the hope that it will be useful,
  9. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. # GNU General Public License for more details.
  12. #
  13. # You should have received a copy of the GNU General Public License
  14. # along with this program. If not, see <http://www.gnu.org/licenses/>.
  15. import gdb
  16. import itertools
  17. import re
  18. import sys
  19. ### Python 2 + Python 3 compatibility code
  20. # Resources about compatibility:
  21. #
  22. # * <http://pythonhosted.org/six/>: Documentation of the "six" module
  23. # FIXME: The handling of e.g. std::basic_string (at least on char)
  24. # probably needs updating to work with Python 3's new string rules.
  25. #
  26. # In particular, Python 3 has a separate type (called byte) for
  27. # bytestrings, and a special b"" syntax for the byte literals; the old
  28. # str() type has been redefined to always store Unicode text.
  29. #
  30. # We probably can't do much about this until this GDB PR is addressed:
  31. # <https://sourceware.org/bugzilla/show_bug.cgi?id=17138>
  32. if sys.version_info[0] > 2:
  33. ### Python 3 stuff
  34. Iterator = object
  35. # Python 3 folds these into the normal functions.
  36. imap = map
  37. izip = zip
  38. # Also, int subsumes long
  39. long = int
  40. else:
  41. ### Python 2 stuff
  42. class Iterator:
  43. """Compatibility mixin for iterators
  44. Instead of writing next() methods for iterators, write
  45. __next__() methods and use this mixin to make them work in
  46. Python 2 as well as Python 3.
  47. Idea stolen from the "six" documentation:
  48. <http://pythonhosted.org/six/#six.Iterator>
  49. """
  50. def next(self):
  51. return self.__next__()
  52. # In Python 2, we still need these from itertools
  53. from itertools import imap, izip
  54. # Try to use the new-style pretty-printing if available.
  55. _use_gdb_pp = True
  56. try:
  57. import gdb.printing
  58. except ImportError:
  59. _use_gdb_pp = False
  60. # Try to install type-printers.
  61. _use_type_printing = False
  62. try:
  63. import gdb.types
  64. if hasattr(gdb.types, 'TypePrinter'):
  65. _use_type_printing = True
  66. except ImportError:
  67. pass
  68. # Starting with the type ORIG, search for the member type NAME. This
  69. # handles searching upward through superclasses. This is needed to
  70. # work around http://sourceware.org/bugzilla/show_bug.cgi?id=13615.
  71. def find_type(orig, name):
  72. typ = orig.strip_typedefs()
  73. while True:
  74. # Strip cv-qualifiers. PR 67440.
  75. search = '%s::%s' % (typ.unqualified(), name)
  76. try:
  77. return gdb.lookup_type(search)
  78. except RuntimeError:
  79. pass
  80. # The type was not found, so try the superclass. We only need
  81. # to check the first superclass, so we don't bother with
  82. # anything fancier here.
  83. field = typ.fields()[0]
  84. if not field.is_base_class:
  85. raise ValueError("Cannot find type %s::%s" % (str(orig), name))
  86. typ = field.type
  87. _versioned_namespace = '__8::'
  88. def is_specialization_of(type, template_name):
  89. "Test if a type is a given template instantiation."
  90. global _versioned_namespace
  91. if _versioned_namespace:
  92. return re.match('^std::(%s)?%s<.*>$' % (_versioned_namespace, template_name), type) is not None
  93. return re.match('^std::%s<.*>$' % template_name, type) is not None
  94. def strip_versioned_namespace(typename):
  95. global _versioned_namespace
  96. if _versioned_namespace:
  97. return typename.replace(_versioned_namespace, '')
  98. return typename
  99. def strip_inline_namespaces(type_str):
  100. "Remove known inline namespaces from the canonical name of a type."
  101. type_str = strip_versioned_namespace(type_str)
  102. type_str = type_str.replace('std::__cxx11::', 'std::')
  103. expt_ns = 'std::experimental::'
  104. for lfts_ns in ('fundamentals_v1', 'fundamentals_v2'):
  105. type_str = type_str.replace(expt_ns+lfts_ns+'::', expt_ns)
  106. fs_ns = expt_ns + 'filesystem::'
  107. type_str = type_str.replace(fs_ns+'v1::', fs_ns)
  108. return type_str
  109. def get_template_arg_list(type_obj):
  110. "Return a type's template arguments as a list"
  111. n = 0
  112. template_args = []
  113. while True:
  114. try:
  115. template_args.append(type_obj.template_argument(n))
  116. except:
  117. return template_args
  118. n += 1
  119. class SmartPtrIterator(Iterator):
  120. "An iterator for smart pointer types with a single 'child' value"
  121. def __init__(self, val):
  122. self.val = val
  123. def __iter__(self):
  124. return self
  125. def __next__(self):
  126. if self.val is None:
  127. raise StopIteration
  128. self.val, val = None, self.val
  129. return ('get()', val)
  130. class SharedPointerPrinter:
  131. "Print a shared_ptr or weak_ptr"
  132. def __init__ (self, typename, val):
  133. self.typename = strip_versioned_namespace(typename)
  134. self.val = val
  135. self.pointer = val['_M_ptr']
  136. def children (self):
  137. return SmartPtrIterator(self.pointer)
  138. def to_string (self):
  139. state = 'empty'
  140. refcounts = self.val['_M_refcount']['_M_pi']
  141. if refcounts != 0:
  142. usecount = refcounts['_M_use_count']
  143. weakcount = refcounts['_M_weak_count']
  144. if usecount == 0:
  145. state = 'expired, weak count %d' % weakcount
  146. else:
  147. state = 'use count %d, weak count %d' % (usecount, weakcount - 1)
  148. return '%s<%s> (%s)' % (self.typename, str(self.val.type.template_argument(0)), state)
  149. class UniquePointerPrinter:
  150. "Print a unique_ptr"
  151. def __init__ (self, typename, val):
  152. self.val = val
  153. impl_type = val.type.fields()[0].type.tag
  154. if is_specialization_of(impl_type, '__uniq_ptr_impl'): # New implementation
  155. self.pointer = val['_M_t']['_M_t']['_M_head_impl']
  156. elif is_specialization_of(impl_type, 'tuple'):
  157. self.pointer = val['_M_t']['_M_head_impl']
  158. else:
  159. raise ValueError("Unsupported implementation for unique_ptr: %s" % impl_type)
  160. def children (self):
  161. return SmartPtrIterator(self.pointer)
  162. def to_string (self):
  163. return ('std::unique_ptr<%s>' % (str(self.val.type.template_argument(0))))
  164. def get_value_from_aligned_membuf(buf, valtype):
  165. """Returns the value held in a __gnu_cxx::__aligned_membuf."""
  166. return buf['_M_storage'].address.cast(valtype.pointer()).dereference()
  167. def get_value_from_list_node(node):
  168. """Returns the value held in an _List_node<_Val>"""
  169. try:
  170. member = node.type.fields()[1].name
  171. if member == '_M_data':
  172. # C++03 implementation, node contains the value as a member
  173. return node['_M_data']
  174. elif member == '_M_storage':
  175. # C++11 implementation, node stores value in __aligned_membuf
  176. valtype = node.type.template_argument(0)
  177. return get_value_from_aligned_membuf(node['_M_storage'], valtype)
  178. except:
  179. pass
  180. raise ValueError("Unsupported implementation for %s" % str(node.type))
  181. class StdListPrinter:
  182. "Print a std::list"
  183. class _iterator(Iterator):
  184. def __init__(self, nodetype, head):
  185. self.nodetype = nodetype
  186. self.base = head['_M_next']
  187. self.head = head.address
  188. self.count = 0
  189. def __iter__(self):
  190. return self
  191. def __next__(self):
  192. if self.base == self.head:
  193. raise StopIteration
  194. elt = self.base.cast(self.nodetype).dereference()
  195. self.base = elt['_M_next']
  196. count = self.count
  197. self.count = self.count + 1
  198. val = get_value_from_list_node(elt)
  199. return ('[%d]' % count, val)
  200. def __init__(self, typename, val):
  201. self.typename = strip_versioned_namespace(typename)
  202. self.val = val
  203. def children(self):
  204. nodetype = find_type(self.val.type, '_Node')
  205. nodetype = nodetype.strip_typedefs().pointer()
  206. return self._iterator(nodetype, self.val['_M_impl']['_M_node'])
  207. def to_string(self):
  208. if self.val['_M_impl']['_M_node'].address == self.val['_M_impl']['_M_node']['_M_next']:
  209. return 'empty %s' % (self.typename)
  210. return '%s' % (self.typename)
  211. class NodeIteratorPrinter:
  212. def __init__(self, typename, val, contname):
  213. self.val = val
  214. self.typename = typename
  215. self.contname = contname
  216. def to_string(self):
  217. if not self.val['_M_node']:
  218. return 'non-dereferenceable iterator for std::%s' % (self.contname)
  219. nodetype = find_type(self.val.type, '_Node')
  220. nodetype = nodetype.strip_typedefs().pointer()
  221. node = self.val['_M_node'].cast(nodetype).dereference()
  222. return str(get_value_from_list_node(node))
  223. class StdListIteratorPrinter(NodeIteratorPrinter):
  224. "Print std::list::iterator"
  225. def __init__(self, typename, val):
  226. NodeIteratorPrinter.__init__(self, typename, val, 'list')
  227. class StdFwdListIteratorPrinter(NodeIteratorPrinter):
  228. "Print std::forward_list::iterator"
  229. def __init__(self, typename, val):
  230. NodeIteratorPrinter.__init__(self, typename, val, 'forward_list')
  231. class StdSlistPrinter:
  232. "Print a __gnu_cxx::slist"
  233. class _iterator(Iterator):
  234. def __init__(self, nodetype, head):
  235. self.nodetype = nodetype
  236. self.base = head['_M_head']['_M_next']
  237. self.count = 0
  238. def __iter__(self):
  239. return self
  240. def __next__(self):
  241. if self.base == 0:
  242. raise StopIteration
  243. elt = self.base.cast(self.nodetype).dereference()
  244. self.base = elt['_M_next']
  245. count = self.count
  246. self.count = self.count + 1
  247. return ('[%d]' % count, elt['_M_data'])
  248. def __init__(self, typename, val):
  249. self.val = val
  250. def children(self):
  251. nodetype = find_type(self.val.type, '_Node')
  252. nodetype = nodetype.strip_typedefs().pointer()
  253. return self._iterator(nodetype, self.val)
  254. def to_string(self):
  255. if self.val['_M_head']['_M_next'] == 0:
  256. return 'empty __gnu_cxx::slist'
  257. return '__gnu_cxx::slist'
  258. class StdSlistIteratorPrinter:
  259. "Print __gnu_cxx::slist::iterator"
  260. def __init__(self, typename, val):
  261. self.val = val
  262. def to_string(self):
  263. if not self.val['_M_node']:
  264. return 'non-dereferenceable iterator for __gnu_cxx::slist'
  265. nodetype = find_type(self.val.type, '_Node')
  266. nodetype = nodetype.strip_typedefs().pointer()
  267. return str(self.val['_M_node'].cast(nodetype).dereference()['_M_data'])
  268. class StdVectorPrinter:
  269. "Print a std::vector"
  270. class _iterator(Iterator):
  271. def __init__ (self, start, finish, bitvec):
  272. self.bitvec = bitvec
  273. if bitvec:
  274. self.item = start['_M_p']
  275. self.so = start['_M_offset']
  276. self.finish = finish['_M_p']
  277. self.fo = finish['_M_offset']
  278. itype = self.item.dereference().type
  279. self.isize = 8 * itype.sizeof
  280. else:
  281. self.item = start
  282. self.finish = finish
  283. self.count = 0
  284. def __iter__(self):
  285. return self
  286. def __next__(self):
  287. count = self.count
  288. self.count = self.count + 1
  289. if self.bitvec:
  290. if self.item == self.finish and self.so >= self.fo:
  291. raise StopIteration
  292. elt = self.item.dereference()
  293. if elt & (1 << self.so):
  294. obit = 1
  295. else:
  296. obit = 0
  297. self.so = self.so + 1
  298. if self.so >= self.isize:
  299. self.item = self.item + 1
  300. self.so = 0
  301. return ('[%d]' % count, obit)
  302. else:
  303. if self.item == self.finish:
  304. raise StopIteration
  305. elt = self.item.dereference()
  306. self.item = self.item + 1
  307. return ('[%d]' % count, elt)
  308. def __init__(self, typename, val):
  309. self.typename = strip_versioned_namespace(typename)
  310. self.val = val
  311. self.is_bool = val.type.template_argument(0).code == gdb.TYPE_CODE_BOOL
  312. def children(self):
  313. return self._iterator(self.val['_M_impl']['_M_start'],
  314. self.val['_M_impl']['_M_finish'],
  315. self.is_bool)
  316. def to_string(self):
  317. start = self.val['_M_impl']['_M_start']
  318. finish = self.val['_M_impl']['_M_finish']
  319. end = self.val['_M_impl']['_M_end_of_storage']
  320. if self.is_bool:
  321. start = self.val['_M_impl']['_M_start']['_M_p']
  322. so = self.val['_M_impl']['_M_start']['_M_offset']
  323. finish = self.val['_M_impl']['_M_finish']['_M_p']
  324. fo = self.val['_M_impl']['_M_finish']['_M_offset']
  325. itype = start.dereference().type
  326. bl = 8 * itype.sizeof
  327. length = (bl - so) + bl * ((finish - start) - 1) + fo
  328. capacity = bl * (end - start)
  329. return ('%s<bool> of length %d, capacity %d'
  330. % (self.typename, int (length), int (capacity)))
  331. else:
  332. return ('%s of length %d, capacity %d'
  333. % (self.typename, int (finish - start), int (end - start)))
  334. def display_hint(self):
  335. return 'array'
  336. class StdVectorIteratorPrinter:
  337. "Print std::vector::iterator"
  338. def __init__(self, typename, val):
  339. self.val = val
  340. def to_string(self):
  341. if not self.val['_M_current']:
  342. return 'non-dereferenceable iterator for std::vector'
  343. return str(self.val['_M_current'].dereference())
  344. class StdTuplePrinter:
  345. "Print a std::tuple"
  346. class _iterator(Iterator):
  347. def __init__ (self, head):
  348. self.head = head
  349. # Set the base class as the initial head of the
  350. # tuple.
  351. nodes = self.head.type.fields ()
  352. if len (nodes) == 1:
  353. # Set the actual head to the first pair.
  354. self.head = self.head.cast (nodes[0].type)
  355. elif len (nodes) != 0:
  356. raise ValueError("Top of tuple tree does not consist of a single node.")
  357. self.count = 0
  358. def __iter__ (self):
  359. return self
  360. def __next__ (self):
  361. # Check for further recursions in the inheritance tree.
  362. # For a GCC 5+ tuple self.head is None after visiting all nodes:
  363. if not self.head:
  364. raise StopIteration
  365. nodes = self.head.type.fields ()
  366. # For a GCC 4.x tuple there is a final node with no fields:
  367. if len (nodes) == 0:
  368. raise StopIteration
  369. # Check that this iteration has an expected structure.
  370. if len (nodes) > 2:
  371. raise ValueError("Cannot parse more than 2 nodes in a tuple tree.")
  372. if len (nodes) == 1:
  373. # This is the last node of a GCC 5+ std::tuple.
  374. impl = self.head.cast (nodes[0].type)
  375. self.head = None
  376. else:
  377. # Either a node before the last node, or the last node of
  378. # a GCC 4.x tuple (which has an empty parent).
  379. # - Left node is the next recursion parent.
  380. # - Right node is the actual class contained in the tuple.
  381. # Process right node.
  382. impl = self.head.cast (nodes[1].type)
  383. # Process left node and set it as head.
  384. self.head = self.head.cast (nodes[0].type)
  385. self.count = self.count + 1
  386. # Finally, check the implementation. If it is
  387. # wrapped in _M_head_impl return that, otherwise return
  388. # the value "as is".
  389. fields = impl.type.fields ()
  390. if len (fields) < 1 or fields[0].name != "_M_head_impl":
  391. return ('[%d]' % self.count, impl)
  392. else:
  393. return ('[%d]' % self.count, impl['_M_head_impl'])
  394. def __init__ (self, typename, val):
  395. self.typename = strip_versioned_namespace(typename)
  396. self.val = val;
  397. def children (self):
  398. return self._iterator (self.val)
  399. def to_string (self):
  400. if len (self.val.type.fields ()) == 0:
  401. return 'empty %s' % (self.typename)
  402. return '%s containing' % (self.typename)
  403. class StdStackOrQueuePrinter:
  404. "Print a std::stack or std::queue"
  405. def __init__ (self, typename, val):
  406. self.typename = strip_versioned_namespace(typename)
  407. self.visualizer = gdb.default_visualizer(val['c'])
  408. def children (self):
  409. return self.visualizer.children()
  410. def to_string (self):
  411. return '%s wrapping: %s' % (self.typename,
  412. self.visualizer.to_string())
  413. def display_hint (self):
  414. if hasattr (self.visualizer, 'display_hint'):
  415. return self.visualizer.display_hint ()
  416. return None
  417. class RbtreeIterator(Iterator):
  418. """
  419. Turn an RB-tree-based container (std::map, std::set etc.) into
  420. a Python iterable object.
  421. """
  422. def __init__(self, rbtree):
  423. self.size = rbtree['_M_t']['_M_impl']['_M_node_count']
  424. self.node = rbtree['_M_t']['_M_impl']['_M_header']['_M_left']
  425. self.count = 0
  426. def __iter__(self):
  427. return self
  428. def __len__(self):
  429. return int (self.size)
  430. def __next__(self):
  431. if self.count == self.size:
  432. raise StopIteration
  433. result = self.node
  434. self.count = self.count + 1
  435. if self.count < self.size:
  436. # Compute the next node.
  437. node = self.node
  438. if node.dereference()['_M_right']:
  439. node = node.dereference()['_M_right']
  440. while node.dereference()['_M_left']:
  441. node = node.dereference()['_M_left']
  442. else:
  443. parent = node.dereference()['_M_parent']
  444. while node == parent.dereference()['_M_right']:
  445. node = parent
  446. parent = parent.dereference()['_M_parent']
  447. if node.dereference()['_M_right'] != parent:
  448. node = parent
  449. self.node = node
  450. return result
  451. def get_value_from_Rb_tree_node(node):
  452. """Returns the value held in an _Rb_tree_node<_Val>"""
  453. try:
  454. member = node.type.fields()[1].name
  455. if member == '_M_value_field':
  456. # C++03 implementation, node contains the value as a member
  457. return node['_M_value_field']
  458. elif member == '_M_storage':
  459. # C++11 implementation, node stores value in __aligned_membuf
  460. valtype = node.type.template_argument(0)
  461. return get_value_from_aligned_membuf(node['_M_storage'], valtype)
  462. except:
  463. pass
  464. raise ValueError("Unsupported implementation for %s" % str(node.type))
  465. # This is a pretty printer for std::_Rb_tree_iterator (which is
  466. # std::map::iterator), and has nothing to do with the RbtreeIterator
  467. # class above.
  468. class StdRbtreeIteratorPrinter:
  469. "Print std::map::iterator, std::set::iterator, etc."
  470. def __init__ (self, typename, val):
  471. self.val = val
  472. valtype = self.val.type.template_argument(0).strip_typedefs()
  473. nodetype = '_Rb_tree_node<' + str(valtype) + '>'
  474. if _versioned_namespace and typename.startswith('std::' + _versioned_namespace):
  475. nodetype = _versioned_namespace + nodetype
  476. nodetype = gdb.lookup_type('std::' + nodetype)
  477. self.link_type = nodetype.strip_typedefs().pointer()
  478. def to_string (self):
  479. if not self.val['_M_node']:
  480. return 'non-dereferenceable iterator for associative container'
  481. node = self.val['_M_node'].cast(self.link_type).dereference()
  482. return str(get_value_from_Rb_tree_node(node))
  483. class StdDebugIteratorPrinter:
  484. "Print a debug enabled version of an iterator"
  485. def __init__ (self, typename, val):
  486. self.val = val
  487. # Just strip away the encapsulating __gnu_debug::_Safe_iterator
  488. # and return the wrapped iterator value.
  489. def to_string (self):
  490. base_type = gdb.lookup_type('__gnu_debug::_Safe_iterator_base')
  491. itype = self.val.type.template_argument(0)
  492. safe_seq = self.val.cast(base_type)['_M_sequence']
  493. if not safe_seq:
  494. return str(self.val.cast(itype))
  495. if self.val['_M_version'] != safe_seq['_M_version']:
  496. return "invalid iterator"
  497. return str(self.val.cast(itype))
  498. def num_elements(num):
  499. """Return either "1 element" or "N elements" depending on the argument."""
  500. return '1 element' if num == 1 else '%d elements' % num
  501. class StdMapPrinter:
  502. "Print a std::map or std::multimap"
  503. # Turn an RbtreeIterator into a pretty-print iterator.
  504. class _iter(Iterator):
  505. def __init__(self, rbiter, type):
  506. self.rbiter = rbiter
  507. self.count = 0
  508. self.type = type
  509. def __iter__(self):
  510. return self
  511. def __next__(self):
  512. if self.count % 2 == 0:
  513. n = next(self.rbiter)
  514. n = n.cast(self.type).dereference()
  515. n = get_value_from_Rb_tree_node(n)
  516. self.pair = n
  517. item = n['first']
  518. else:
  519. item = self.pair['second']
  520. result = ('[%d]' % self.count, item)
  521. self.count = self.count + 1
  522. return result
  523. def __init__ (self, typename, val):
  524. self.typename = strip_versioned_namespace(typename)
  525. self.val = val
  526. def to_string (self):
  527. return '%s with %s' % (self.typename,
  528. num_elements(len(RbtreeIterator (self.val))))
  529. def children (self):
  530. rep_type = find_type(self.val.type, '_Rep_type')
  531. node = find_type(rep_type, '_Link_type')
  532. node = node.strip_typedefs()
  533. return self._iter (RbtreeIterator (self.val), node)
  534. def display_hint (self):
  535. return 'map'
  536. class StdSetPrinter:
  537. "Print a std::set or std::multiset"
  538. # Turn an RbtreeIterator into a pretty-print iterator.
  539. class _iter(Iterator):
  540. def __init__(self, rbiter, type):
  541. self.rbiter = rbiter
  542. self.count = 0
  543. self.type = type
  544. def __iter__(self):
  545. return self
  546. def __next__(self):
  547. item = next(self.rbiter)
  548. item = item.cast(self.type).dereference()
  549. item = get_value_from_Rb_tree_node(item)
  550. # FIXME: this is weird ... what to do?
  551. # Maybe a 'set' display hint?
  552. result = ('[%d]' % self.count, item)
  553. self.count = self.count + 1
  554. return result
  555. def __init__ (self, typename, val):
  556. self.typename = strip_versioned_namespace(typename)
  557. self.val = val
  558. def to_string (self):
  559. return '%s with %s' % (self.typename,
  560. num_elements(len(RbtreeIterator (self.val))))
  561. def children (self):
  562. rep_type = find_type(self.val.type, '_Rep_type')
  563. node = find_type(rep_type, '_Link_type')
  564. node = node.strip_typedefs()
  565. return self._iter (RbtreeIterator (self.val), node)
  566. class StdBitsetPrinter:
  567. "Print a std::bitset"
  568. def __init__(self, typename, val):
  569. self.typename = strip_versioned_namespace(typename)
  570. self.val = val
  571. def to_string (self):
  572. # If template_argument handled values, we could print the
  573. # size. Or we could use a regexp on the type.
  574. return '%s' % (self.typename)
  575. def children (self):
  576. try:
  577. # An empty bitset may not have any members which will
  578. # result in an exception being thrown.
  579. words = self.val['_M_w']
  580. except:
  581. return []
  582. wtype = words.type
  583. # The _M_w member can be either an unsigned long, or an
  584. # array. This depends on the template specialization used.
  585. # If it is a single long, convert to a single element list.
  586. if wtype.code == gdb.TYPE_CODE_ARRAY:
  587. tsize = wtype.target ().sizeof
  588. else:
  589. words = [words]
  590. tsize = wtype.sizeof
  591. nwords = wtype.sizeof / tsize
  592. result = []
  593. byte = 0
  594. while byte < nwords:
  595. w = words[byte]
  596. bit = 0
  597. while w != 0:
  598. if (w & 1) != 0:
  599. # Another spot where we could use 'set'?
  600. result.append(('[%d]' % (byte * tsize * 8 + bit), 1))
  601. bit = bit + 1
  602. w = w >> 1
  603. byte = byte + 1
  604. return result
  605. class StdDequePrinter:
  606. "Print a std::deque"
  607. class _iter(Iterator):
  608. def __init__(self, node, start, end, last, buffer_size):
  609. self.node = node
  610. self.p = start
  611. self.end = end
  612. self.last = last
  613. self.buffer_size = buffer_size
  614. self.count = 0
  615. def __iter__(self):
  616. return self
  617. def __next__(self):
  618. if self.p == self.last:
  619. raise StopIteration
  620. result = ('[%d]' % self.count, self.p.dereference())
  621. self.count = self.count + 1
  622. # Advance the 'cur' pointer.
  623. self.p = self.p + 1
  624. if self.p == self.end:
  625. # If we got to the end of this bucket, move to the
  626. # next bucket.
  627. self.node = self.node + 1
  628. self.p = self.node[0]
  629. self.end = self.p + self.buffer_size
  630. return result
  631. def __init__(self, typename, val):
  632. self.typename = strip_versioned_namespace(typename)
  633. self.val = val
  634. self.elttype = val.type.template_argument(0)
  635. size = self.elttype.sizeof
  636. if size < 512:
  637. self.buffer_size = int (512 / size)
  638. else:
  639. self.buffer_size = 1
  640. def to_string(self):
  641. start = self.val['_M_impl']['_M_start']
  642. end = self.val['_M_impl']['_M_finish']
  643. delta_n = end['_M_node'] - start['_M_node'] - 1
  644. delta_s = start['_M_last'] - start['_M_cur']
  645. delta_e = end['_M_cur'] - end['_M_first']
  646. size = self.buffer_size * delta_n + delta_s + delta_e
  647. return '%s with %s' % (self.typename, num_elements(long(size)))
  648. def children(self):
  649. start = self.val['_M_impl']['_M_start']
  650. end = self.val['_M_impl']['_M_finish']
  651. return self._iter(start['_M_node'], start['_M_cur'], start['_M_last'],
  652. end['_M_cur'], self.buffer_size)
  653. def display_hint (self):
  654. return 'array'
  655. class StdDequeIteratorPrinter:
  656. "Print std::deque::iterator"
  657. def __init__(self, typename, val):
  658. self.val = val
  659. def to_string(self):
  660. if not self.val['_M_cur']:
  661. return 'non-dereferenceable iterator for std::deque'
  662. return str(self.val['_M_cur'].dereference())
  663. class StdStringPrinter:
  664. "Print a std::basic_string of some kind"
  665. def __init__(self, typename, val):
  666. self.val = val
  667. self.new_string = typename.find("::__cxx11::basic_string") != -1
  668. def to_string(self):
  669. # Make sure &string works, too.
  670. type = self.val.type
  671. if type.code == gdb.TYPE_CODE_REF:
  672. type = type.target ()
  673. # Calculate the length of the string so that to_string returns
  674. # the string according to length, not according to first null
  675. # encountered.
  676. ptr = self.val ['_M_dataplus']['_M_p']
  677. if self.new_string:
  678. length = self.val['_M_string_length']
  679. # https://sourceware.org/bugzilla/show_bug.cgi?id=17728
  680. ptr = ptr.cast(ptr.type.strip_typedefs())
  681. else:
  682. realtype = type.unqualified ().strip_typedefs ()
  683. reptype = gdb.lookup_type (str (realtype) + '::_Rep').pointer ()
  684. header = ptr.cast(reptype) - 1
  685. length = header.dereference ()['_M_length']
  686. if hasattr(ptr, "lazy_string"):
  687. return ptr.lazy_string (length = length)
  688. return ptr.string (length = length)
  689. def display_hint (self):
  690. return 'string'
  691. class Tr1HashtableIterator(Iterator):
  692. def __init__ (self, hash):
  693. self.buckets = hash['_M_buckets']
  694. self.bucket = 0
  695. self.bucket_count = hash['_M_bucket_count']
  696. self.node_type = find_type(hash.type, '_Node').pointer()
  697. self.node = 0
  698. while self.bucket != self.bucket_count:
  699. self.node = self.buckets[self.bucket]
  700. if self.node:
  701. break
  702. self.bucket = self.bucket + 1
  703. def __iter__ (self):
  704. return self
  705. def __next__ (self):
  706. if self.node == 0:
  707. raise StopIteration
  708. node = self.node.cast(self.node_type)
  709. result = node.dereference()['_M_v']
  710. self.node = node.dereference()['_M_next'];
  711. if self.node == 0:
  712. self.bucket = self.bucket + 1
  713. while self.bucket != self.bucket_count:
  714. self.node = self.buckets[self.bucket]
  715. if self.node:
  716. break
  717. self.bucket = self.bucket + 1
  718. return result
  719. class StdHashtableIterator(Iterator):
  720. def __init__(self, hash):
  721. self.node = hash['_M_before_begin']['_M_nxt']
  722. self.node_type = find_type(hash.type, '__node_type').pointer()
  723. def __iter__(self):
  724. return self
  725. def __next__(self):
  726. if self.node == 0:
  727. raise StopIteration
  728. elt = self.node.cast(self.node_type).dereference()
  729. self.node = elt['_M_nxt']
  730. valptr = elt['_M_storage'].address
  731. valptr = valptr.cast(elt.type.template_argument(0).pointer())
  732. return valptr.dereference()
  733. class Tr1UnorderedSetPrinter:
  734. "Print a tr1::unordered_set"
  735. def __init__ (self, typename, val):
  736. self.typename = strip_versioned_namespace(typename)
  737. self.val = val
  738. def hashtable (self):
  739. if self.typename.startswith('std::tr1'):
  740. return self.val
  741. return self.val['_M_h']
  742. def to_string (self):
  743. count = self.hashtable()['_M_element_count']
  744. return '%s with %s' % (self.typename, num_elements(count))
  745. @staticmethod
  746. def format_count (i):
  747. return '[%d]' % i
  748. def children (self):
  749. counter = imap (self.format_count, itertools.count())
  750. if self.typename.startswith('std::tr1'):
  751. return izip (counter, Tr1HashtableIterator (self.hashtable()))
  752. return izip (counter, StdHashtableIterator (self.hashtable()))
  753. class Tr1UnorderedMapPrinter:
  754. "Print a tr1::unordered_map"
  755. def __init__ (self, typename, val):
  756. self.typename = strip_versioned_namespace(typename)
  757. self.val = val
  758. def hashtable (self):
  759. if self.typename.startswith('std::tr1'):
  760. return self.val
  761. return self.val['_M_h']
  762. def to_string (self):
  763. count = self.hashtable()['_M_element_count']
  764. return '%s with %s' % (self.typename, num_elements(count))
  765. @staticmethod
  766. def flatten (list):
  767. for elt in list:
  768. for i in elt:
  769. yield i
  770. @staticmethod
  771. def format_one (elt):
  772. return (elt['first'], elt['second'])
  773. @staticmethod
  774. def format_count (i):
  775. return '[%d]' % i
  776. def children (self):
  777. counter = imap (self.format_count, itertools.count())
  778. # Map over the hash table and flatten the result.
  779. if self.typename.startswith('std::tr1'):
  780. data = self.flatten (imap (self.format_one, Tr1HashtableIterator (self.hashtable())))
  781. # Zip the two iterators together.
  782. return izip (counter, data)
  783. data = self.flatten (imap (self.format_one, StdHashtableIterator (self.hashtable())))
  784. # Zip the two iterators together.
  785. return izip (counter, data)
  786. def display_hint (self):
  787. return 'map'
  788. class StdForwardListPrinter:
  789. "Print a std::forward_list"
  790. class _iterator(Iterator):
  791. def __init__(self, nodetype, head):
  792. self.nodetype = nodetype
  793. self.base = head['_M_next']
  794. self.count = 0
  795. def __iter__(self):
  796. return self
  797. def __next__(self):
  798. if self.base == 0:
  799. raise StopIteration
  800. elt = self.base.cast(self.nodetype).dereference()
  801. self.base = elt['_M_next']
  802. count = self.count
  803. self.count = self.count + 1
  804. valptr = elt['_M_storage'].address
  805. valptr = valptr.cast(elt.type.template_argument(0).pointer())
  806. return ('[%d]' % count, valptr.dereference())
  807. def __init__(self, typename, val):
  808. self.val = val
  809. self.typename = strip_versioned_namespace(typename)
  810. def children(self):
  811. nodetype = find_type(self.val.type, '_Node')
  812. nodetype = nodetype.strip_typedefs().pointer()
  813. return self._iterator(nodetype, self.val['_M_impl']['_M_head'])
  814. def to_string(self):
  815. if self.val['_M_impl']['_M_head']['_M_next'] == 0:
  816. return 'empty %s' % self.typename
  817. return '%s' % self.typename
  818. class SingleObjContainerPrinter(object):
  819. "Base class for printers of containers of single objects"
  820. def __init__ (self, val, viz, hint = None):
  821. self.contained_value = val
  822. self.visualizer = viz
  823. self.hint = hint
  824. def _recognize(self, type):
  825. """Return TYPE as a string after applying type printers"""
  826. global _use_type_printing
  827. if not _use_type_printing:
  828. return str(type)
  829. return gdb.types.apply_type_recognizers(gdb.types.get_type_recognizers(),
  830. type) or str(type)
  831. class _contained(Iterator):
  832. def __init__ (self, val):
  833. self.val = val
  834. def __iter__ (self):
  835. return self
  836. def __next__(self):
  837. if self.val is None:
  838. raise StopIteration
  839. retval = self.val
  840. self.val = None
  841. return ('[contained value]', retval)
  842. def children (self):
  843. if self.contained_value is None:
  844. return self._contained (None)
  845. if hasattr (self.visualizer, 'children'):
  846. return self.visualizer.children ()
  847. return self._contained (self.contained_value)
  848. def display_hint (self):
  849. # if contained value is a map we want to display in the same way
  850. if hasattr (self.visualizer, 'children') and hasattr (self.visualizer, 'display_hint'):
  851. return self.visualizer.display_hint ()
  852. return self.hint
  853. class StdExpAnyPrinter(SingleObjContainerPrinter):
  854. "Print a std::any or std::experimental::any"
  855. def __init__ (self, typename, val):
  856. self.typename = strip_versioned_namespace(typename)
  857. self.typename = re.sub('^std::experimental::fundamentals_v\d::', 'std::experimental::', self.typename, 1)
  858. self.val = val
  859. self.contained_type = None
  860. contained_value = None
  861. visualizer = None
  862. mgr = self.val['_M_manager']
  863. if mgr != 0:
  864. func = gdb.block_for_pc(int(mgr.cast(gdb.lookup_type('intptr_t'))))
  865. if not func:
  866. raise ValueError("Invalid function pointer in %s" % self.typename)
  867. rx = r"""({0}::_Manager_\w+<.*>)::_S_manage""".format(typename)
  868. m = re.match(rx, func.function.name)
  869. if not m:
  870. raise ValueError("Unknown manager function in %s" % self.typename)
  871. mgrname = m.group(1)
  872. # FIXME need to expand 'std::string' so that gdb.lookup_type works
  873. if 'std::string' in mgrname:
  874. mgrname = re.sub("std::string(?!\w)", str(gdb.lookup_type('std::string').strip_typedefs()), m.group(1))
  875. mgrtype = gdb.lookup_type(mgrname)
  876. self.contained_type = mgrtype.template_argument(0)
  877. valptr = None
  878. if '::_Manager_internal' in mgrname:
  879. valptr = self.val['_M_storage']['_M_buffer'].address
  880. elif '::_Manager_external' in mgrname:
  881. valptr = self.val['_M_storage']['_M_ptr']
  882. else:
  883. raise ValueError("Unknown manager function in %s" % self.typename)
  884. contained_value = valptr.cast(self.contained_type.pointer()).dereference()
  885. visualizer = gdb.default_visualizer(contained_value)
  886. super(StdExpAnyPrinter, self).__init__ (contained_value, visualizer)
  887. def to_string (self):
  888. if self.contained_type is None:
  889. return '%s [no contained value]' % self.typename
  890. desc = "%s containing " % self.typename
  891. if hasattr (self.visualizer, 'children'):
  892. return desc + self.visualizer.to_string ()
  893. valtype = self._recognize (self.contained_type)
  894. return desc + strip_versioned_namespace(str(valtype))
  895. class StdExpOptionalPrinter(SingleObjContainerPrinter):
  896. "Print a std::optional or std::experimental::optional"
  897. def __init__ (self, typename, val):
  898. valtype = self._recognize (val.type.template_argument(0))
  899. self.typename = strip_versioned_namespace(typename)
  900. self.typename = re.sub('^std::(experimental::|)(fundamentals_v\d::|)(.*)', r'std::\1\3<%s>' % valtype, self.typename, 1)
  901. if not self.typename.startswith('std::experimental'):
  902. val = val['_M_payload']
  903. self.val = val
  904. contained_value = val['_M_payload'] if self.val['_M_engaged'] else None
  905. visualizer = gdb.default_visualizer (val['_M_payload'])
  906. super (StdExpOptionalPrinter, self).__init__ (contained_value, visualizer)
  907. def to_string (self):
  908. if self.contained_value is None:
  909. return "%s [no contained value]" % self.typename
  910. if hasattr (self.visualizer, 'children'):
  911. return "%s containing %s" % (self.typename,
  912. self.visualizer.to_string())
  913. return self.typename
  914. class StdVariantPrinter(SingleObjContainerPrinter):
  915. "Print a std::variant"
  916. def __init__(self, typename, val):
  917. alternatives = get_template_arg_list(val.type)
  918. self.typename = strip_versioned_namespace(typename)
  919. self.typename = "%s<%s>" % (self.typename, ', '.join([self._recognize(alt) for alt in alternatives]))
  920. self.index = val['_M_index']
  921. if self.index >= len(alternatives):
  922. self.contained_type = None
  923. contained_value = None
  924. visualizer = None
  925. else:
  926. self.contained_type = alternatives[int(self.index)]
  927. addr = val['_M_u']['_M_first']['_M_storage'].address
  928. contained_value = addr.cast(self.contained_type.pointer()).dereference()
  929. visualizer = gdb.default_visualizer(contained_value)
  930. super (StdVariantPrinter, self).__init__(contained_value, visualizer, 'array')
  931. def to_string(self):
  932. if self.contained_value is None:
  933. return "%s [no contained value]" % self.typename
  934. if hasattr(self.visualizer, 'children'):
  935. return "%s [index %d] containing %s" % (self.typename, self.index,
  936. self.visualizer.to_string())
  937. return "%s [index %d]" % (self.typename, self.index)
  938. class StdNodeHandlePrinter(SingleObjContainerPrinter):
  939. "Print a container node handle"
  940. def __init__(self, typename, val):
  941. self.value_type = val.type.template_argument(1)
  942. nodetype = val.type.template_argument(2).template_argument(0)
  943. self.is_rb_tree_node = is_specialization_of(nodetype.name, '_Rb_tree_node')
  944. self.is_map_node = val.type.template_argument(0) != self.value_type
  945. nodeptr = val['_M_ptr']
  946. if nodeptr:
  947. if self.is_rb_tree_node:
  948. contained_value = get_value_from_Rb_tree_node(nodeptr.dereference())
  949. else:
  950. contained_value = get_value_from_aligned_membuf(nodeptr['_M_storage'],
  951. self.value_type)
  952. visualizer = gdb.default_visualizer(contained_value)
  953. else:
  954. contained_value = None
  955. visualizer = None
  956. optalloc = val['_M_alloc']
  957. self.alloc = optalloc['_M_payload'] if optalloc['_M_engaged'] else None
  958. super(StdNodeHandlePrinter, self).__init__(contained_value, visualizer,
  959. 'array')
  960. def to_string(self):
  961. desc = 'node handle for '
  962. if not self.is_rb_tree_node:
  963. desc += 'unordered '
  964. if self.is_map_node:
  965. desc += 'map';
  966. else:
  967. desc += 'set';
  968. if self.contained_value:
  969. desc += ' with element'
  970. if hasattr(self.visualizer, 'children'):
  971. return "%s = %s" % (desc, self.visualizer.to_string())
  972. return desc
  973. else:
  974. return 'empty %s' % desc
  975. class StdExpStringViewPrinter:
  976. "Print a std::basic_string_view or std::experimental::basic_string_view"
  977. def __init__ (self, typename, val):
  978. self.val = val
  979. def to_string (self):
  980. ptr = self.val['_M_str']
  981. len = self.val['_M_len']
  982. if hasattr (ptr, "lazy_string"):
  983. return ptr.lazy_string (length = len)
  984. return ptr.string (length = len)
  985. def display_hint (self):
  986. return 'string'
  987. class StdExpPathPrinter:
  988. "Print a std::experimental::filesystem::path"
  989. def __init__ (self, typename, val):
  990. self.val = val
  991. start = self.val['_M_cmpts']['_M_impl']['_M_start']
  992. finish = self.val['_M_cmpts']['_M_impl']['_M_finish']
  993. self.num_cmpts = int (finish - start)
  994. def _path_type(self):
  995. t = str(self.val['_M_type'])
  996. if t[-9:] == '_Root_dir':
  997. return "root-directory"
  998. if t[-10:] == '_Root_name':
  999. return "root-name"
  1000. return None
  1001. def to_string (self):
  1002. path = "%s" % self.val ['_M_pathname']
  1003. if self.num_cmpts == 0:
  1004. t = self._path_type()
  1005. if t:
  1006. path = '%s [%s]' % (path, t)
  1007. return "filesystem::path %s" % path
  1008. class _iterator(Iterator):
  1009. def __init__(self, cmpts):
  1010. self.item = cmpts['_M_impl']['_M_start']
  1011. self.finish = cmpts['_M_impl']['_M_finish']
  1012. self.count = 0
  1013. def __iter__(self):
  1014. return self
  1015. def __next__(self):
  1016. if self.item == self.finish:
  1017. raise StopIteration
  1018. item = self.item.dereference()
  1019. count = self.count
  1020. self.count = self.count + 1
  1021. self.item = self.item + 1
  1022. path = item['_M_pathname']
  1023. t = StdExpPathPrinter(item.type.name, item)._path_type()
  1024. if not t:
  1025. t = count
  1026. return ('[%s]' % t, path)
  1027. def children(self):
  1028. return self._iterator(self.val['_M_cmpts'])
  1029. class StdPairPrinter:
  1030. "Print a std::pair object, with 'first' and 'second' as children"
  1031. def __init__(self, typename, val):
  1032. self.val = val
  1033. class _iter(Iterator):
  1034. "An iterator for std::pair types. Returns 'first' then 'second'."
  1035. def __init__(self, val):
  1036. self.val = val
  1037. self.which = 'first'
  1038. def __iter__(self):
  1039. return self
  1040. def __next__(self):
  1041. if self.which is None:
  1042. raise StopIteration
  1043. which = self.which
  1044. if which == 'first':
  1045. self.which = 'second'
  1046. else:
  1047. self.which = None
  1048. return (which, self.val[which])
  1049. def children(self):
  1050. return self._iter(self.val)
  1051. def to_string(self):
  1052. return None
  1053. # A "regular expression" printer which conforms to the
  1054. # "SubPrettyPrinter" protocol from gdb.printing.
  1055. class RxPrinter(object):
  1056. def __init__(self, name, function):
  1057. super(RxPrinter, self).__init__()
  1058. self.name = name
  1059. self.function = function
  1060. self.enabled = True
  1061. def invoke(self, value):
  1062. if not self.enabled:
  1063. return None
  1064. if value.type.code == gdb.TYPE_CODE_REF:
  1065. if hasattr(gdb.Value,"referenced_value"):
  1066. value = value.referenced_value()
  1067. return self.function(self.name, value)
  1068. # A pretty-printer that conforms to the "PrettyPrinter" protocol from
  1069. # gdb.printing. It can also be used directly as an old-style printer.
  1070. class Printer(object):
  1071. def __init__(self, name):
  1072. super(Printer, self).__init__()
  1073. self.name = name
  1074. self.subprinters = []
  1075. self.lookup = {}
  1076. self.enabled = True
  1077. self.compiled_rx = re.compile('^([a-zA-Z0-9_:]+)(<.*>)?$')
  1078. def add(self, name, function):
  1079. # A small sanity check.
  1080. # FIXME
  1081. if not self.compiled_rx.match(name):
  1082. raise ValueError('libstdc++ programming error: "%s" does not match' % name)
  1083. printer = RxPrinter(name, function)
  1084. self.subprinters.append(printer)
  1085. self.lookup[name] = printer
  1086. # Add a name using _GLIBCXX_BEGIN_NAMESPACE_VERSION.
  1087. def add_version(self, base, name, function):
  1088. self.add(base + name, function)
  1089. if _versioned_namespace:
  1090. vbase = re.sub('^(std|__gnu_cxx)::', r'\g<0>%s' % _versioned_namespace, base)
  1091. self.add(vbase + name, function)
  1092. # Add a name using _GLIBCXX_BEGIN_NAMESPACE_CONTAINER.
  1093. def add_container(self, base, name, function):
  1094. self.add_version(base, name, function)
  1095. self.add_version(base + '__cxx1998::', name, function)
  1096. @staticmethod
  1097. def get_basic_type(type):
  1098. # If it points to a reference, get the reference.
  1099. if type.code == gdb.TYPE_CODE_REF:
  1100. type = type.target ()
  1101. # Get the unqualified type, stripped of typedefs.
  1102. type = type.unqualified ().strip_typedefs ()
  1103. return type.tag
  1104. def __call__(self, val):
  1105. typename = self.get_basic_type(val.type)
  1106. if not typename:
  1107. return None
  1108. # All the types we match are template types, so we can use a
  1109. # dictionary.
  1110. match = self.compiled_rx.match(typename)
  1111. if not match:
  1112. return None
  1113. basename = match.group(1)
  1114. if val.type.code == gdb.TYPE_CODE_REF:
  1115. if hasattr(gdb.Value,"referenced_value"):
  1116. val = val.referenced_value()
  1117. if basename in self.lookup:
  1118. return self.lookup[basename].invoke(val)
  1119. # Cannot find a pretty printer. Return None.
  1120. return None
  1121. libstdcxx_printer = None
  1122. class TemplateTypePrinter(object):
  1123. r"""
  1124. A type printer for class templates with default template arguments.
  1125. Recognizes specializations of class templates and prints them without
  1126. any template arguments that use a default template argument.
  1127. Type printers are recursively applied to the template arguments.
  1128. e.g. replace "std::vector<T, std::allocator<T> >" with "std::vector<T>".
  1129. """
  1130. def __init__(self, name, defargs):
  1131. self.name = name
  1132. self.defargs = defargs
  1133. self.enabled = True
  1134. class _recognizer(object):
  1135. "The recognizer class for TemplateTypePrinter."
  1136. def __init__(self, name, defargs):
  1137. self.name = name
  1138. self.defargs = defargs
  1139. # self.type_obj = None
  1140. def recognize(self, type_obj):
  1141. """
  1142. If type_obj is a specialization of self.name that uses all the
  1143. default template arguments for the class template, then return
  1144. a string representation of the type without default arguments.
  1145. Otherwise, return None.
  1146. """
  1147. if type_obj.tag is None:
  1148. return None
  1149. if not type_obj.tag.startswith(self.name):
  1150. return None
  1151. template_args = get_template_arg_list(type_obj)
  1152. displayed_args = []
  1153. require_defaulted = False
  1154. for n in range(len(template_args)):
  1155. # The actual template argument in the type:
  1156. targ = template_args[n]
  1157. # The default template argument for the class template:
  1158. defarg = self.defargs.get(n)
  1159. if defarg is not None:
  1160. # Substitute other template arguments into the default:
  1161. defarg = defarg.format(*template_args)
  1162. # Fail to recognize the type (by returning None)
  1163. # unless the actual argument is the same as the default.
  1164. try:
  1165. if targ != gdb.lookup_type(defarg):
  1166. return None
  1167. except gdb.error:
  1168. # Type lookup failed, just use string comparison:
  1169. if targ.tag != defarg:
  1170. return None
  1171. # All subsequent args must have defaults:
  1172. require_defaulted = True
  1173. elif require_defaulted:
  1174. return None
  1175. else:
  1176. # Recursively apply recognizers to the template argument
  1177. # and add it to the arguments that will be displayed:
  1178. displayed_args.append(self._recognize_subtype(targ))
  1179. # This assumes no class templates in the nested-name-specifier:
  1180. template_name = type_obj.tag[0:type_obj.tag.find('<')]
  1181. template_name = strip_inline_namespaces(template_name)
  1182. return template_name + '<' + ', '.join(displayed_args) + '>'
  1183. def _recognize_subtype(self, type_obj):
  1184. """Convert a gdb.Type to a string by applying recognizers,
  1185. or if that fails then simply converting to a string."""
  1186. if type_obj.code == gdb.TYPE_CODE_PTR:
  1187. return self._recognize_subtype(type_obj.target()) + '*'
  1188. if type_obj.code == gdb.TYPE_CODE_ARRAY:
  1189. type_str = self._recognize_subtype(type_obj.target())
  1190. if str(type_obj.strip_typedefs()).endswith('[]'):
  1191. return type_str + '[]' # array of unknown bound
  1192. return "%s[%d]" % (type_str, type_obj.range()[1] + 1)
  1193. if type_obj.code == gdb.TYPE_CODE_REF:
  1194. return self._recognize_subtype(type_obj.target()) + '&'
  1195. if hasattr(gdb, 'TYPE_CODE_RVALUE_REF'):
  1196. if type_obj.code == gdb.TYPE_CODE_RVALUE_REF:
  1197. return self._recognize_subtype(type_obj.target()) + '&&'
  1198. type_str = gdb.types.apply_type_recognizers(
  1199. gdb.types.get_type_recognizers(), type_obj)
  1200. if type_str:
  1201. return type_str
  1202. return str(type_obj)
  1203. def instantiate(self):
  1204. "Return a recognizer object for this type printer."
  1205. return self._recognizer(self.name, self.defargs)
  1206. def add_one_template_type_printer(obj, name, defargs):
  1207. r"""
  1208. Add a type printer for a class template with default template arguments.
  1209. Args:
  1210. name (str): The template-name of the class template.
  1211. defargs (dict int:string) The default template arguments.
  1212. Types in defargs can refer to the Nth template-argument using {N}
  1213. (with zero-based indices).
  1214. e.g. 'unordered_map' has these defargs:
  1215. { 2: 'std::hash<{0}>',
  1216. 3: 'std::equal_to<{0}>',
  1217. 4: 'std::allocator<std::pair<const {0}, {1}> >' }
  1218. """
  1219. printer = TemplateTypePrinter('std::'+name, defargs)
  1220. gdb.types.register_type_printer(obj, printer)
  1221. if _versioned_namespace:
  1222. # Add second type printer for same type in versioned namespace:
  1223. ns = 'std::' + _versioned_namespace
  1224. # PR 86112 Cannot use dict comprehension here:
  1225. defargs = dict((n, d.replace('std::', ns)) for (n,d) in defargs.items())
  1226. printer = TemplateTypePrinter(ns+name, defargs)
  1227. gdb.types.register_type_printer(obj, printer)
  1228. class FilteringTypePrinter(object):
  1229. r"""
  1230. A type printer that uses typedef names for common template specializations.
  1231. Args:
  1232. match (str): The class template to recognize.
  1233. name (str): The typedef-name that will be used instead.
  1234. Checks if a specialization of the class template 'match' is the same type
  1235. as the typedef 'name', and prints it as 'name' instead.
  1236. e.g. if an instantiation of std::basic_istream<C, T> is the same type as
  1237. std::istream then print it as std::istream.
  1238. """
  1239. def __init__(self, match, name):
  1240. self.match = match
  1241. self.name = name
  1242. self.enabled = True
  1243. class _recognizer(object):
  1244. "The recognizer class for TemplateTypePrinter."
  1245. def __init__(self, match, name):
  1246. self.match = match
  1247. self.name = name
  1248. self.type_obj = None
  1249. def recognize(self, type_obj):
  1250. """
  1251. If type_obj starts with self.match and is the same type as
  1252. self.name then return self.name, otherwise None.
  1253. """
  1254. if type_obj.tag is None:
  1255. return None
  1256. if self.type_obj is None:
  1257. if not type_obj.tag.startswith(self.match):
  1258. # Filter didn't match.
  1259. return None
  1260. try:
  1261. self.type_obj = gdb.lookup_type(self.name).strip_typedefs()
  1262. except:
  1263. pass
  1264. if self.type_obj == type_obj:
  1265. return strip_inline_namespaces(self.name)
  1266. return None
  1267. def instantiate(self):
  1268. "Return a recognizer object for this type printer."
  1269. return self._recognizer(self.match, self.name)
  1270. def add_one_type_printer(obj, match, name):
  1271. printer = FilteringTypePrinter('std::' + match, 'std::' + name)
  1272. gdb.types.register_type_printer(obj, printer)
  1273. if _versioned_namespace:
  1274. ns = 'std::' + _versioned_namespace
  1275. printer = FilteringTypePrinter(ns + match, ns + name)
  1276. gdb.types.register_type_printer(obj, printer)
  1277. def register_type_printers(obj):
  1278. global _use_type_printing
  1279. if not _use_type_printing:
  1280. return
  1281. # Add type printers for typedefs std::string, std::wstring etc.
  1282. for ch in ('', 'w', 'u16', 'u32'):
  1283. add_one_type_printer(obj, 'basic_string', ch + 'string')
  1284. add_one_type_printer(obj, '__cxx11::basic_string',
  1285. '__cxx11::' + ch + 'string')
  1286. add_one_type_printer(obj, 'basic_string_view', ch + 'string_view')
  1287. # Add type printers for typedefs std::istream, std::wistream etc.
  1288. for ch in ('', 'w'):
  1289. for x in ('ios', 'streambuf', 'istream', 'ostream', 'iostream',
  1290. 'filebuf', 'ifstream', 'ofstream', 'fstream'):
  1291. add_one_type_printer(obj, 'basic_' + x, ch + x)
  1292. for x in ('stringbuf', 'istringstream', 'ostringstream',
  1293. 'stringstream'):
  1294. add_one_type_printer(obj, 'basic_' + x, ch + x)
  1295. # <sstream> types are in __cxx11 namespace, but typedefs aren'x:
  1296. add_one_type_printer(obj, '__cxx11::basic_' + x, ch + x)
  1297. # Add type printers for typedefs regex, wregex, cmatch, wcmatch etc.
  1298. for abi in ('', '__cxx11::'):
  1299. for ch in ('', 'w'):
  1300. add_one_type_printer(obj, abi + 'basic_regex', abi + ch + 'regex')
  1301. for ch in ('c', 's', 'wc', 'ws'):
  1302. add_one_type_printer(obj, abi + 'match_results', abi + ch + 'match')
  1303. for x in ('sub_match', 'regex_iterator', 'regex_token_iterator'):
  1304. add_one_type_printer(obj, abi + x, abi + ch + x)
  1305. # Note that we can't have a printer for std::wstreampos, because
  1306. # it is the same type as std::streampos.
  1307. add_one_type_printer(obj, 'fpos', 'streampos')
  1308. # Add type printers for <chrono> typedefs.
  1309. for dur in ('nanoseconds', 'microseconds', 'milliseconds',
  1310. 'seconds', 'minutes', 'hours'):
  1311. add_one_type_printer(obj, 'duration', dur)
  1312. # Add type printers for <random> typedefs.
  1313. add_one_type_printer(obj, 'linear_congruential_engine', 'minstd_rand0')
  1314. add_one_type_printer(obj, 'linear_congruential_engine', 'minstd_rand')
  1315. add_one_type_printer(obj, 'mersenne_twister_engine', 'mt19937')
  1316. add_one_type_printer(obj, 'mersenne_twister_engine', 'mt19937_64')
  1317. add_one_type_printer(obj, 'subtract_with_carry_engine', 'ranlux24_base')
  1318. add_one_type_printer(obj, 'subtract_with_carry_engine', 'ranlux48_base')
  1319. add_one_type_printer(obj, 'discard_block_engine', 'ranlux24')
  1320. add_one_type_printer(obj, 'discard_block_engine', 'ranlux48')
  1321. add_one_type_printer(obj, 'shuffle_order_engine', 'knuth_b')
  1322. # Add type printers for experimental::basic_string_view typedefs.
  1323. ns = 'experimental::fundamentals_v1::'
  1324. for ch in ('', 'w', 'u16', 'u32'):
  1325. add_one_type_printer(obj, ns + 'basic_string_view',
  1326. ns + ch + 'string_view')
  1327. # Do not show defaulted template arguments in class templates.
  1328. add_one_template_type_printer(obj, 'unique_ptr',
  1329. { 1: 'std::default_delete<{0}>' })
  1330. add_one_template_type_printer(obj, 'deque', { 1: 'std::allocator<{0}>'})
  1331. add_one_template_type_printer(obj, 'forward_list', { 1: 'std::allocator<{0}>'})
  1332. add_one_template_type_printer(obj, 'list', { 1: 'std::allocator<{0}>'})
  1333. add_one_template_type_printer(obj, '__cxx11::list', { 1: 'std::allocator<{0}>'})
  1334. add_one_template_type_printer(obj, 'vector', { 1: 'std::allocator<{0}>'})
  1335. add_one_template_type_printer(obj, 'map',
  1336. { 2: 'std::less<{0}>',
  1337. 3: 'std::allocator<std::pair<{0} const, {1}>>' })
  1338. add_one_template_type_printer(obj, 'multimap',
  1339. { 2: 'std::less<{0}>',
  1340. 3: 'std::allocator<std::pair<{0} const, {1}>>' })
  1341. add_one_template_type_printer(obj, 'set',
  1342. { 1: 'std::less<{0}>', 2: 'std::allocator<{0}>' })
  1343. add_one_template_type_printer(obj, 'multiset',
  1344. { 1: 'std::less<{0}>', 2: 'std::allocator<{0}>' })
  1345. add_one_template_type_printer(obj, 'unordered_map',
  1346. { 2: 'std::hash<{0}>',
  1347. 3: 'std::equal_to<{0}>',
  1348. 4: 'std::allocator<std::pair<{0} const, {1}>>'})
  1349. add_one_template_type_printer(obj, 'unordered_multimap',
  1350. { 2: 'std::hash<{0}>',
  1351. 3: 'std::equal_to<{0}>',
  1352. 4: 'std::allocator<std::pair<{0} const, {1}>>'})
  1353. add_one_template_type_printer(obj, 'unordered_set',
  1354. { 1: 'std::hash<{0}>',
  1355. 2: 'std::equal_to<{0}>',
  1356. 3: 'std::allocator<{0}>'})
  1357. add_one_template_type_printer(obj, 'unordered_multiset',
  1358. { 1: 'std::hash<{0}>',
  1359. 2: 'std::equal_to<{0}>',
  1360. 3: 'std::allocator<{0}>'})
  1361. def register_libstdcxx_printers (obj):
  1362. "Register libstdc++ pretty-printers with objfile Obj."
  1363. global _use_gdb_pp
  1364. global libstdcxx_printer
  1365. if _use_gdb_pp:
  1366. gdb.printing.register_pretty_printer(obj, libstdcxx_printer)
  1367. else:
  1368. if obj is None:
  1369. obj = gdb
  1370. obj.pretty_printers.append(libstdcxx_printer)
  1371. register_type_printers(obj)
  1372. def build_libstdcxx_dictionary ():
  1373. global libstdcxx_printer
  1374. libstdcxx_printer = Printer("libstdc++-v6")
  1375. # libstdc++ objects requiring pretty-printing.
  1376. # In order from:
  1377. # http://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/a01847.html
  1378. libstdcxx_printer.add_version('std::', 'basic_string', StdStringPrinter)
  1379. libstdcxx_printer.add_version('std::__cxx11::', 'basic_string', StdStringPrinter)
  1380. libstdcxx_printer.add_container('std::', 'bitset', StdBitsetPrinter)
  1381. libstdcxx_printer.add_container('std::', 'deque', StdDequePrinter)
  1382. libstdcxx_printer.add_container('std::', 'list', StdListPrinter)
  1383. libstdcxx_printer.add_container('std::__cxx11::', 'list', StdListPrinter)
  1384. libstdcxx_printer.add_container('std::', 'map', StdMapPrinter)
  1385. libstdcxx_printer.add_container('std::', 'multimap', StdMapPrinter)
  1386. libstdcxx_printer.add_container('std::', 'multiset', StdSetPrinter)
  1387. libstdcxx_printer.add_version('std::', 'pair', StdPairPrinter)
  1388. libstdcxx_printer.add_version('std::', 'priority_queue',
  1389. StdStackOrQueuePrinter)
  1390. libstdcxx_printer.add_version('std::', 'queue', StdStackOrQueuePrinter)
  1391. libstdcxx_printer.add_version('std::', 'tuple', StdTuplePrinter)
  1392. libstdcxx_printer.add_container('std::', 'set', StdSetPrinter)
  1393. libstdcxx_printer.add_version('std::', 'stack', StdStackOrQueuePrinter)
  1394. libstdcxx_printer.add_version('std::', 'unique_ptr', UniquePointerPrinter)
  1395. libstdcxx_printer.add_container('std::', 'vector', StdVectorPrinter)
  1396. # vector<bool>
  1397. # Printer registrations for classes compiled with -D_GLIBCXX_DEBUG.
  1398. libstdcxx_printer.add('std::__debug::bitset', StdBitsetPrinter)
  1399. libstdcxx_printer.add('std::__debug::deque', StdDequePrinter)
  1400. libstdcxx_printer.add('std::__debug::list', StdListPrinter)
  1401. libstdcxx_printer.add('std::__debug::map', StdMapPrinter)
  1402. libstdcxx_printer.add('std::__debug::multimap', StdMapPrinter)
  1403. libstdcxx_printer.add('std::__debug::multiset', StdSetPrinter)
  1404. libstdcxx_printer.add('std::__debug::priority_queue',
  1405. StdStackOrQueuePrinter)
  1406. libstdcxx_printer.add('std::__debug::queue', StdStackOrQueuePrinter)
  1407. libstdcxx_printer.add('std::__debug::set', StdSetPrinter)
  1408. libstdcxx_printer.add('std::__debug::stack', StdStackOrQueuePrinter)
  1409. libstdcxx_printer.add('std::__debug::unique_ptr', UniquePointerPrinter)
  1410. libstdcxx_printer.add('std::__debug::vector', StdVectorPrinter)
  1411. # These are the TR1 and C++11 printers.
  1412. # For array - the default GDB pretty-printer seems reasonable.
  1413. libstdcxx_printer.add_version('std::', 'shared_ptr', SharedPointerPrinter)
  1414. libstdcxx_printer.add_version('std::', 'weak_ptr', SharedPointerPrinter)
  1415. libstdcxx_printer.add_container('std::', 'unordered_map',
  1416. Tr1UnorderedMapPrinter)
  1417. libstdcxx_printer.add_container('std::', 'unordered_set',
  1418. Tr1UnorderedSetPrinter)
  1419. libstdcxx_printer.add_container('std::', 'unordered_multimap',
  1420. Tr1UnorderedMapPrinter)
  1421. libstdcxx_printer.add_container('std::', 'unordered_multiset',
  1422. Tr1UnorderedSetPrinter)
  1423. libstdcxx_printer.add_container('std::', 'forward_list',
  1424. StdForwardListPrinter)
  1425. libstdcxx_printer.add_version('std::tr1::', 'shared_ptr', SharedPointerPrinter)
  1426. libstdcxx_printer.add_version('std::tr1::', 'weak_ptr', SharedPointerPrinter)
  1427. libstdcxx_printer.add_version('std::tr1::', 'unordered_map',
  1428. Tr1UnorderedMapPrinter)
  1429. libstdcxx_printer.add_version('std::tr1::', 'unordered_set',
  1430. Tr1UnorderedSetPrinter)
  1431. libstdcxx_printer.add_version('std::tr1::', 'unordered_multimap',
  1432. Tr1UnorderedMapPrinter)
  1433. libstdcxx_printer.add_version('std::tr1::', 'unordered_multiset',
  1434. Tr1UnorderedSetPrinter)
  1435. # These are the C++11 printer registrations for -D_GLIBCXX_DEBUG cases.
  1436. # The tr1 namespace containers do not have any debug equivalents,
  1437. # so do not register printers for them.
  1438. libstdcxx_printer.add('std::__debug::unordered_map',
  1439. Tr1UnorderedMapPrinter)
  1440. libstdcxx_printer.add('std::__debug::unordered_set',
  1441. Tr1UnorderedSetPrinter)
  1442. libstdcxx_printer.add('std::__debug::unordered_multimap',
  1443. Tr1UnorderedMapPrinter)
  1444. libstdcxx_printer.add('std::__debug::unordered_multiset',
  1445. Tr1UnorderedSetPrinter)
  1446. libstdcxx_printer.add('std::__debug::forward_list',
  1447. StdForwardListPrinter)
  1448. # Library Fundamentals TS components
  1449. libstdcxx_printer.add_version('std::experimental::fundamentals_v1::',
  1450. 'any', StdExpAnyPrinter)
  1451. libstdcxx_printer.add_version('std::experimental::fundamentals_v1::',
  1452. 'optional', StdExpOptionalPrinter)
  1453. libstdcxx_printer.add_version('std::experimental::fundamentals_v1::',
  1454. 'basic_string_view', StdExpStringViewPrinter)
  1455. # Filesystem TS components
  1456. libstdcxx_printer.add_version('std::experimental::filesystem::v1::',
  1457. 'path', StdExpPathPrinter)
  1458. libstdcxx_printer.add_version('std::experimental::filesystem::v1::__cxx11::',
  1459. 'path', StdExpPathPrinter)
  1460. libstdcxx_printer.add_version('std::filesystem::',
  1461. 'path', StdExpPathPrinter)
  1462. libstdcxx_printer.add_version('std::filesystem::__cxx11::',
  1463. 'path', StdExpPathPrinter)
  1464. # C++17 components
  1465. libstdcxx_printer.add_version('std::',
  1466. 'any', StdExpAnyPrinter)
  1467. libstdcxx_printer.add_version('std::',
  1468. 'optional', StdExpOptionalPrinter)
  1469. libstdcxx_printer.add_version('std::',
  1470. 'basic_string_view', StdExpStringViewPrinter)
  1471. libstdcxx_printer.add_version('std::',
  1472. 'variant', StdVariantPrinter)
  1473. libstdcxx_printer.add_version('std::',
  1474. '_Node_handle', StdNodeHandlePrinter)
  1475. # Extensions.
  1476. libstdcxx_printer.add_version('__gnu_cxx::', 'slist', StdSlistPrinter)
  1477. if True:
  1478. # These shouldn't be necessary, if GDB "print *i" worked.
  1479. # But it often doesn't, so here they are.
  1480. libstdcxx_printer.add_container('std::', '_List_iterator',
  1481. StdListIteratorPrinter)
  1482. libstdcxx_printer.add_container('std::', '_List_const_iterator',
  1483. StdListIteratorPrinter)
  1484. libstdcxx_printer.add_version('std::', '_Rb_tree_iterator',
  1485. StdRbtreeIteratorPrinter)
  1486. libstdcxx_printer.add_version('std::', '_Rb_tree_const_iterator',
  1487. StdRbtreeIteratorPrinter)
  1488. libstdcxx_printer.add_container('std::', '_Deque_iterator',
  1489. StdDequeIteratorPrinter)
  1490. libstdcxx_printer.add_container('std::', '_Deque_const_iterator',
  1491. StdDequeIteratorPrinter)
  1492. libstdcxx_printer.add_version('__gnu_cxx::', '__normal_iterator',
  1493. StdVectorIteratorPrinter)
  1494. libstdcxx_printer.add_version('__gnu_cxx::', '_Slist_iterator',
  1495. StdSlistIteratorPrinter)
  1496. libstdcxx_printer.add_container('std::', '_Fwd_list_iterator',
  1497. StdFwdListIteratorPrinter)
  1498. libstdcxx_printer.add_container('std::', '_Fwd_list_const_iterator',
  1499. StdFwdListIteratorPrinter)
  1500. # Debug (compiled with -D_GLIBCXX_DEBUG) printer
  1501. # registrations.
  1502. libstdcxx_printer.add('__gnu_debug::_Safe_iterator',
  1503. StdDebugIteratorPrinter)
  1504. build_libstdcxx_dictionary ()