PageRenderTime 72ms CodeModel.GetById 30ms RepoModel.GetById 0ms app.codeStats 1ms

/share/qtcreator/dumper/dumper.py

https://bitbucket.org/kyanha/qt-creator
Python | 2003 lines | 1681 code | 147 blank | 175 comment | 256 complexity | 4ec1b0b4622133957ec4292c2cf18dae MD5 | raw file
Possible License(s): LGPL-3.0, LGPL-2.1

Large files files are truncated, but you can click here to view the full file

  1. import sys
  2. import base64
  3. import __builtin__
  4. import os
  5. import os.path
  6. import subprocess
  7. import tempfile
  8. # Fails on Windows.
  9. try:
  10. import curses.ascii
  11. def printableChar(ucs):
  12. if curses.ascii.isprint(ucs):
  13. return ucs
  14. return '?'
  15. except:
  16. def printableChar(ucs):
  17. if ucs >= 32 and ucs <= 126:
  18. return ucs
  19. return '?'
  20. # Fails on SimulatorQt.
  21. tempFileCounter = 0
  22. try:
  23. # Test if 2.6 is used (Windows), trigger exception and default
  24. # to 2nd version.
  25. file = tempfile.NamedTemporaryFile(prefix="py_",delete=True)
  26. file.close()
  27. def createTempFile():
  28. file = tempfile.NamedTemporaryFile(prefix="py_",delete=True)
  29. file.close()
  30. return file.name
  31. except:
  32. def createTempFile():
  33. global tempFileCounter
  34. tempFileCounter += 1
  35. fileName = "%s/py_tmp_%d_%d" \
  36. % (tempfile.gettempdir(), os.getpid(), tempFileCounter)
  37. return fileName
  38. def removeTempFile(name):
  39. try:
  40. os.remove(name)
  41. except:
  42. pass
  43. verbosity = 0
  44. verbosity = 1
  45. # Some "Enums"
  46. # Encodings. Keep that synchronized with DebuggerEncoding in watchutils.h
  47. Unencoded8Bit, \
  48. Base64Encoded8BitWithQuotes, \
  49. Base64Encoded16BitWithQuotes, \
  50. Base64Encoded32BitWithQuotes, \
  51. Base64Encoded16Bit, \
  52. Base64Encoded8Bit, \
  53. Hex2EncodedLatin1, \
  54. Hex4EncodedLittleEndian, \
  55. Hex8EncodedLittleEndian, \
  56. Hex2EncodedUtf8, \
  57. Hex8EncodedBigEndian, \
  58. Hex4EncodedBigEndian, \
  59. Hex4EncodedLittleEndianWithoutQuotes, \
  60. Hex2EncodedLocal8Bit, \
  61. JulianDate, \
  62. MillisecondsSinceMidnight, \
  63. JulianDateAndMillisecondsSinceMidnight, \
  64. Hex2EncodedInt1, \
  65. Hex2EncodedInt2, \
  66. Hex2EncodedInt4, \
  67. Hex2EncodedInt8, \
  68. Hex2EncodedUInt1, \
  69. Hex2EncodedUInt2, \
  70. Hex2EncodedUInt4, \
  71. Hex2EncodedUInt8, \
  72. Hex2EncodedFloat4, \
  73. Hex2EncodedFloat8 \
  74. = range(27)
  75. # Display modes. Keep that synchronized with DebuggerDisplay in watchutils.h
  76. StopDisplay, \
  77. DisplayImageData, \
  78. DisplayUtf16String, \
  79. DisplayImageFile, \
  80. DisplayProcess, \
  81. DisplayLatin1String, \
  82. DisplayUtf8String \
  83. = range(7)
  84. qqStringCutOff = 10000
  85. #
  86. # Gnuplot based display for array-like structures.
  87. #
  88. gnuplotPipe = {}
  89. gnuplotPid = {}
  90. def hasPlot():
  91. fileName = "/usr/bin/gnuplot"
  92. return os.path.isfile(fileName) and os.access(fileName, os.X_OK)
  93. #
  94. # Threads
  95. #
  96. def hasInferiorThreadList():
  97. #return False
  98. try:
  99. a = gdb.inferiors()[0].threads()
  100. return True
  101. except:
  102. return False
  103. #
  104. # VTable
  105. #
  106. def hasVTable(type):
  107. fields = type.fields()
  108. if len(fields) == 0:
  109. return False
  110. if fields[0].is_base_class:
  111. return hasVTable(fields[0].type)
  112. return str(fields[0].type) == "int (**)(void)"
  113. def dynamicTypeName(value):
  114. if hasVTable(value.type):
  115. #vtbl = str(parseAndEvaluate("{int(*)(int)}%s" % long(value.address)))
  116. try:
  117. # Fails on 7.1 due to the missing to_string.
  118. vtbl = gdb.execute("info symbol {int*}%s" % long(value.address),
  119. to_string = True)
  120. pos1 = vtbl.find("vtable ")
  121. if pos1 != -1:
  122. pos1 += 11
  123. pos2 = vtbl.find(" +", pos1)
  124. if pos2 != -1:
  125. return vtbl[pos1 : pos2]
  126. except:
  127. pass
  128. return str(value.type)
  129. def downcast(value):
  130. try:
  131. return value.cast(value.dynamic_type)
  132. except:
  133. pass
  134. #try:
  135. # return value.cast(lookupType(dynamicTypeName(value)))
  136. #except:
  137. # pass
  138. return value
  139. def expensiveDowncast(value):
  140. try:
  141. return value.cast(value.dynamic_type)
  142. except:
  143. pass
  144. try:
  145. return value.cast(lookupType(dynamicTypeName(value)))
  146. except:
  147. pass
  148. return value
  149. typeCache = {}
  150. def lookupType(typestring):
  151. global typeCache
  152. global typesToReport
  153. type = typeCache.get(typestring)
  154. #warn("LOOKUP 1: %s -> %s" % (typestring, type))
  155. if not type is None:
  156. return type
  157. if typestring == "void":
  158. type = gdb.lookup_type(typestring)
  159. typeCache[typestring] = type
  160. typesToReport[typestring] = type
  161. return type
  162. try:
  163. type = gdb.parse_and_eval("{%s}&main" % typestring).type
  164. if not type is None:
  165. typeCache[typestring] = type
  166. typesToReport[typestring] = type
  167. return type
  168. except:
  169. pass
  170. # See http://sourceware.org/bugzilla/show_bug.cgi?id=13269
  171. # gcc produces "{anonymous}", gdb "(anonymous namespace)"
  172. # "<unnamed>" has been seen too. The only thing gdb
  173. # understands when reading things back is "(anonymous namespace)"
  174. if typestring.find("{anonymous}") != -1:
  175. ts = typestring
  176. ts = ts.replace("{anonymous}", "(anonymous namespace)")
  177. type = lookupType(ts)
  178. if not type is None:
  179. typeCache[typestring] = type
  180. typesToReport[typestring] = type
  181. return type
  182. #warn(" RESULT FOR 7.2: '%s': %s" % (typestring, type))
  183. # This part should only trigger for
  184. # gdb 7.1 for types with namespace separators.
  185. # And anonymous namespaces.
  186. ts = typestring
  187. while True:
  188. #warn("TS: '%s'" % ts)
  189. if ts.startswith("class "):
  190. ts = ts[6:]
  191. elif ts.startswith("struct "):
  192. ts = ts[7:]
  193. elif ts.startswith("const "):
  194. ts = ts[6:]
  195. elif ts.startswith("volatile "):
  196. ts = ts[9:]
  197. elif ts.startswith("enum "):
  198. ts = ts[5:]
  199. elif ts.endswith(" const"):
  200. ts = ts[:-6]
  201. elif ts.endswith(" volatile"):
  202. ts = ts[:-9]
  203. elif ts.endswith("*const"):
  204. ts = ts[:-5]
  205. elif ts.endswith("*volatile"):
  206. ts = ts[:-8]
  207. else:
  208. break
  209. if ts.endswith('*'):
  210. type = lookupType(ts[0:-1])
  211. if not type is None:
  212. type = type.pointer()
  213. typeCache[typestring] = type
  214. typesToReport[typestring] = type
  215. return type
  216. try:
  217. #warn("LOOKING UP '%s'" % ts)
  218. type = gdb.lookup_type(ts)
  219. except RuntimeError, error:
  220. #warn("LOOKING UP '%s': %s" % (ts, error))
  221. # See http://sourceware.org/bugzilla/show_bug.cgi?id=11912
  222. exp = "(class '%s'*)0" % ts
  223. try:
  224. type = parseAndEvaluate(exp).type.target()
  225. except:
  226. # Can throw "RuntimeError: No type named class Foo."
  227. pass
  228. except:
  229. #warn("LOOKING UP '%s' FAILED" % ts)
  230. pass
  231. if not type is None:
  232. typeCache[typestring] = type
  233. typesToReport[typestring] = type
  234. return type
  235. # This could still be None as gdb.lookup_type("char[3]") generates
  236. # "RuntimeError: No type named char[3]"
  237. typeCache[typestring] = type
  238. typesToReport[typestring] = type
  239. return type
  240. def cleanAddress(addr):
  241. if addr is None:
  242. return "<no address>"
  243. # We cannot use str(addr) as it yields rubbish for char pointers
  244. # that might trigger Unicode encoding errors.
  245. #return addr.cast(lookupType("void").pointer())
  246. # We do not use "hex(...)" as it (sometimes?) adds a "L" suffix.
  247. return "0x%x" % long(addr)
  248. def extractTemplateArgument(type, position):
  249. level = 0
  250. skipSpace = False
  251. inner = ""
  252. type = str(type)
  253. for c in type[type.find('<') + 1 : -1]:
  254. if c == '<':
  255. inner += c
  256. level += 1
  257. elif c == '>':
  258. level -= 1
  259. inner += c
  260. elif c == ',':
  261. if level == 0:
  262. if position == 0:
  263. return inner
  264. position -= 1
  265. inner = ""
  266. else:
  267. inner += c
  268. skipSpace = True
  269. else:
  270. if skipSpace and c == ' ':
  271. pass
  272. else:
  273. inner += c
  274. skipSpace = False
  275. return inner
  276. def templateArgument(type, position):
  277. try:
  278. # This fails on stock 7.2 with
  279. # "RuntimeError: No type named myns::QObject.\n"
  280. return type.template_argument(position)
  281. except:
  282. # That's something like "myns::QList<...>"
  283. return lookupType(extractTemplateArgument(type.strip_typedefs(), position))
  284. # Workaround for gdb < 7.1
  285. def numericTemplateArgument(type, position):
  286. try:
  287. return int(type.template_argument(position))
  288. except RuntimeError, error:
  289. # ": No type named 30."
  290. msg = str(error)
  291. msg = msg[14:-1]
  292. # gdb at least until 7.4 produces for std::array<int, 4u>
  293. # for template_argument(1): RuntimeError: No type named 4u.
  294. if msg[-1] == 'u':
  295. msg = msg[0:-1]
  296. return int(msg)
  297. class OutputSafer:
  298. def __init__(self, d):
  299. self.d = d
  300. def __enter__(self):
  301. self.savedOutput = self.d.output
  302. self.d.output = []
  303. def __exit__(self, exType, exValue, exTraceBack):
  304. if self.d.passExceptions and not exType is None:
  305. showException("OUTPUTSAFER", exType, exValue, exTraceBack)
  306. self.d.output = self.savedOutput
  307. else:
  308. self.savedOutput.extend(self.d.output)
  309. self.d.output = self.savedOutput
  310. return False
  311. class NoAddress:
  312. def __init__(self, d):
  313. self.d = d
  314. def __enter__(self):
  315. self.savedPrintsAddress = self.d.currentPrintsAddress
  316. self.d.currentPrintsAddress = False
  317. def __exit__(self, exType, exValue, exTraceBack):
  318. self.d.currentPrintsAddress = self.savedPrintsAddress
  319. class SubItem:
  320. def __init__(self, d, component):
  321. self.d = d
  322. self.iname = "%s.%s" % (d.currentIName, component)
  323. self.name = component
  324. def __enter__(self):
  325. self.d.put('{')
  326. #if not self.name is None:
  327. if isinstance(self.name, str):
  328. self.d.put('name="%s",' % self.name)
  329. self.savedIName = self.d.currentIName
  330. self.savedValue = self.d.currentValue
  331. self.savedValuePriority = self.d.currentValuePriority
  332. self.savedValueEncoding = self.d.currentValueEncoding
  333. self.savedType = self.d.currentType
  334. self.savedTypePriority = self.d.currentTypePriority
  335. self.d.currentIName = self.iname
  336. self.d.currentValuePriority = -100
  337. self.d.currentValueEncoding = None
  338. self.d.currentType = ""
  339. self.d.currentTypePriority = -100
  340. def __exit__(self, exType, exValue, exTraceBack):
  341. #warn(" CURRENT VALUE: %s %s %s" % (self.d.currentValue,
  342. # self.d.currentValueEncoding, self.d.currentValuePriority))
  343. if not exType is None:
  344. if self.d.passExceptions:
  345. showException("SUBITEM", exType, exValue, exTraceBack)
  346. self.d.putNumChild(0)
  347. self.d.putValue("<not accessible>")
  348. try:
  349. #warn("TYPE VALUE: %s" % self.d.currentValue)
  350. typeName = stripClassTag(self.d.currentType)
  351. #warn("TYPE: '%s' DEFAULT: '%s' % (typeName, self.d.currentChildType))
  352. if len(typeName) > 0 and typeName != self.d.currentChildType:
  353. self.d.put('type="%s",' % typeName) # str(type.unqualified()) ?
  354. if self.d.currentValue is None:
  355. self.d.put('value="<not accessible>",numchild="0",')
  356. else:
  357. if not self.d.currentValueEncoding is None:
  358. self.d.put('valueencoded="%d",' % self.d.currentValueEncoding)
  359. self.d.put('value="%s",' % self.d.currentValue)
  360. except:
  361. pass
  362. self.d.put('},')
  363. self.d.currentIName = self.savedIName
  364. self.d.currentValue = self.savedValue
  365. self.d.currentValuePriority = self.savedValuePriority
  366. self.d.currentValueEncoding = self.savedValueEncoding
  367. self.d.currentType = self.savedType
  368. self.d.currentTypePriority = self.savedTypePriority
  369. return True
  370. class TopLevelItem(SubItem):
  371. def __init__(self, d, iname):
  372. self.d = d
  373. self.iname = iname
  374. self.name = None
  375. class UnnamedSubItem(SubItem):
  376. def __init__(self, d, component):
  377. self.d = d
  378. self.iname = "%s.%s" % (self.d.currentIName, component)
  379. self.name = None
  380. class Children:
  381. def __init__(self, d, numChild = 1, childType = None, childNumChild = None,
  382. maxNumChild = None, addrBase = None, addrStep = None):
  383. self.d = d
  384. self.numChild = numChild
  385. self.childNumChild = childNumChild
  386. self.maxNumChild = maxNumChild
  387. self.addrBase = addrBase
  388. self.addrStep = addrStep
  389. self.printsAddress = True
  390. if childType is None:
  391. self.childType = None
  392. else:
  393. self.childType = stripClassTag(str(childType))
  394. self.d.put('childtype="%s",' % self.childType)
  395. if childNumChild is None:
  396. if isSimpleType(childType):
  397. self.d.put('childnumchild="0",')
  398. self.childNumChild = 0
  399. elif childType.code == PointerCode:
  400. self.d.put('childnumchild="1",')
  401. self.childNumChild = 1
  402. else:
  403. self.d.put('childnumchild="%s",' % childNumChild)
  404. self.childNumChild = childNumChild
  405. try:
  406. if not addrBase is None and not addrStep is None:
  407. self.d.put('addrbase="0x%x",' % long(addrBase))
  408. self.d.put('addrstep="0x%x",' % long(addrStep))
  409. self.printsAddress = False
  410. except:
  411. warn("ADDRBASE: %s" % addrBase)
  412. #warn("CHILDREN: %s %s %s" % (numChild, childType, childNumChild))
  413. def __enter__(self):
  414. self.savedChildType = self.d.currentChildType
  415. self.savedChildNumChild = self.d.currentChildNumChild
  416. self.savedNumChild = self.d.currentNumChild
  417. self.savedMaxNumChild = self.d.currentMaxNumChild
  418. self.savedPrintsAddress = self.d.currentPrintsAddress
  419. self.d.currentChildType = self.childType
  420. self.d.currentChildNumChild = self.childNumChild
  421. self.d.currentNumChild = self.numChild
  422. self.d.currentMaxNumChild = self.maxNumChild
  423. self.d.currentPrintsAddress = self.printsAddress
  424. self.d.put("children=[")
  425. def __exit__(self, exType, exValue, exTraceBack):
  426. if not exType is None:
  427. if self.d.passExceptions:
  428. showException("CHILDREN", exType, exValue, exTraceBack)
  429. self.d.putNumChild(0)
  430. self.d.putValue("<not accessible>")
  431. if not self.d.currentMaxNumChild is None:
  432. if self.d.currentMaxNumChild < self.d.currentNumChild:
  433. self.d.put('{name="<incomplete>",value="",type="",numchild="0"},')
  434. self.d.currentChildType = self.savedChildType
  435. self.d.currentChildNumChild = self.savedChildNumChild
  436. self.d.currentNumChild = self.savedNumChild
  437. self.d.currentMaxNumChild = self.savedMaxNumChild
  438. self.d.currentPrintsAddress = self.savedPrintsAddress
  439. self.d.put('],')
  440. return True
  441. def value(expr):
  442. value = parseAndEvaluate(expr)
  443. try:
  444. return int(value)
  445. except:
  446. return str(value)
  447. def isSimpleType(typeobj):
  448. code = typeobj.code
  449. return code == BoolCode \
  450. or code == CharCode \
  451. or code == IntCode \
  452. or code == FloatCode \
  453. or code == EnumCode
  454. def simpleEncoding(typeobj):
  455. code = typeobj.code
  456. if code == BoolCode or code == CharCode:
  457. return Hex2EncodedInt1
  458. if code == IntCode:
  459. if str(typeobj).find("unsigned") >= 0:
  460. if typeobj.sizeof == 1:
  461. return Hex2EncodedUInt1
  462. if typeobj.sizeof == 2:
  463. return Hex2EncodedUInt2
  464. if typeobj.sizeof == 4:
  465. return Hex2EncodedUInt4
  466. if typeobj.sizeof == 8:
  467. return Hex2EncodedUInt8
  468. else:
  469. if typeobj.sizeof == 1:
  470. return Hex2EncodedInt1
  471. if typeobj.sizeof == 2:
  472. return Hex2EncodedInt2
  473. if typeobj.sizeof == 4:
  474. return Hex2EncodedInt4
  475. if typeobj.sizeof == 8:
  476. return Hex2EncodedInt8
  477. if code == FloatCode:
  478. if typeobj.sizeof == 4:
  479. return Hex2EncodedFloat4
  480. if typeobj.sizeof == 8:
  481. return Hex2EncodedFloat8
  482. return None
  483. def check(exp):
  484. if not exp:
  485. raise RuntimeError("Check failed")
  486. def checkSimpleRef(ref):
  487. count = ref["_q_value"]
  488. check(count > 0)
  489. check(count < 1000000)
  490. def checkRef(ref):
  491. try:
  492. count = ref["atomic"]["_q_value"] # Qt 5.
  493. minimum = -1
  494. except:
  495. count = ref["_q_value"] # Qt 4.
  496. minimum = 0
  497. # Assume there aren't a million references to any object.
  498. check(count >= minimum)
  499. check(count < 1000000)
  500. #def couldBePointer(p, align):
  501. # type = lookupType("unsigned int")
  502. # ptr = gdb.Value(p).cast(type)
  503. # d = int(str(ptr))
  504. # warn("CHECKING : %s %d " % (p, ((d & 3) == 0 and (d > 1000 or d == 0))))
  505. # return (d & (align - 1)) and (d > 1000 or d == 0)
  506. def checkAccess(p, align = 1):
  507. return p.dereference()
  508. def checkContents(p, expected, align = 1):
  509. if int(p.dereference()) != expected:
  510. raise RuntimeError("Contents check failed")
  511. def checkPointer(p, align = 1):
  512. if not isNull(p):
  513. p.dereference()
  514. def isAccessible(p):
  515. try:
  516. long(p)
  517. return True
  518. except:
  519. return False
  520. def isNull(p):
  521. # The following can cause evaluation to abort with "UnicodeEncodeError"
  522. # for invalid char *, as their "contents" is being examined
  523. #s = str(p)
  524. #return s == "0x0" or s.startswith("0x0 ")
  525. #try:
  526. # # Can fail with: "RuntimeError: Cannot access memory at address 0x5"
  527. # return p.cast(lookupType("void").pointer()) == 0
  528. #except:
  529. # return False
  530. try:
  531. # Can fail with: "RuntimeError: Cannot access memory at address 0x5"
  532. return long(p) == 0
  533. except:
  534. return False
  535. movableTypes = set([
  536. "QBrush", "QBitArray", "QByteArray", "QCustomTypeInfo", "QChar", "QDate",
  537. "QDateTime", "QFileInfo", "QFixed", "QFixedPoint", "QFixedSize",
  538. "QHashDummyValue", "QIcon", "QImage", "QLine", "QLineF", "QLatin1Char",
  539. "QLocale", "QMatrix", "QModelIndex", "QPoint", "QPointF", "QPen",
  540. "QPersistentModelIndex", "QResourceRoot", "QRect", "QRectF", "QRegExp",
  541. "QSize", "QSizeF", "QString", "QTime", "QTextBlock", "QUrl", "QVariant",
  542. "QXmlStreamAttribute", "QXmlStreamNamespaceDeclaration",
  543. "QXmlStreamNotationDeclaration", "QXmlStreamEntityDeclaration"
  544. ])
  545. def stripClassTag(typeName):
  546. if typeName.startswith("class "):
  547. return typeName[6:]
  548. if typeName.startswith("struct "):
  549. return typeName[7:]
  550. if typeName.startswith("const "):
  551. return typeName[6:]
  552. if typeName.startswith("volatile "):
  553. return typeName[9:]
  554. return typeName
  555. def checkPointerRange(p, n):
  556. for i in xrange(n):
  557. checkPointer(p)
  558. ++p
  559. def call2(value, func, args):
  560. # args is a tuple.
  561. arg = ""
  562. for i in range(len(args)):
  563. if i:
  564. arg += ','
  565. a = args[i]
  566. if (':' in a) and not ("'" in a):
  567. arg = "'%s'" % a
  568. else:
  569. arg += a
  570. #warn("CALL: %s -> %s(%s)" % (value, func, arg))
  571. type = stripClassTag(str(value.type))
  572. if type.find(":") >= 0:
  573. type = "'" + type + "'"
  574. # 'class' is needed, see http://sourceware.org/bugzilla/show_bug.cgi?id=11912
  575. exp = "((class %s*)%s)->%s(%s)" % (type, value.address, func, arg)
  576. #warn("CALL: %s" % exp)
  577. result = None
  578. try:
  579. result = parseAndEvaluate(exp)
  580. except:
  581. pass
  582. #warn(" -> %s" % result)
  583. return result
  584. def call(value, func, *args):
  585. return call2(value, func, args)
  586. def makeValue(type, init):
  587. type = "::" + stripClassTag(str(type));
  588. # Avoid malloc symbol clash with QVector.
  589. gdb.execute("set $d = (%s*)calloc(sizeof(%s), 1)" % (type, type))
  590. gdb.execute("set *$d = {%s}" % init)
  591. value = parseAndEvaluate("$d").dereference()
  592. #warn(" TYPE: %s" % value.type)
  593. #warn(" ADDR: %s" % value.address)
  594. #warn(" VALUE: %s" % value)
  595. return value
  596. def makeStdString(init):
  597. # Works only for small allocators, but they are usually empty.
  598. gdb.execute("set $d=(std::string*)calloc(sizeof(std::string), 2)");
  599. gdb.execute("call($d->basic_string(\"" + init +
  600. "\",*(std::allocator<char>*)(1+$d)))")
  601. value = parseAndEvaluate("$d").dereference()
  602. #warn(" TYPE: %s" % value.type)
  603. #warn(" ADDR: %s" % value.address)
  604. #warn(" VALUE: %s" % value)
  605. return value
  606. def makeExpression(value):
  607. type = "::" + stripClassTag(str(value.type))
  608. #warn(" TYPE: %s" % type)
  609. #exp = "(*(%s*)(&%s))" % (type, value.address)
  610. exp = "(*(%s*)(%s))" % (type, value.address)
  611. #warn(" EXP: %s" % exp)
  612. return exp
  613. qqNs = None
  614. def qtNamespace():
  615. # FIXME: This only works when call from inside a Qt function frame.
  616. global qqNs
  617. if not qqNs is None:
  618. return qqNs
  619. try:
  620. str = catchCliOutput("ptype QString::Null")[0]
  621. # The result looks like:
  622. # "type = const struct myns::QString::Null {"
  623. # " <no data fields>"
  624. # "}"
  625. pos1 = str.find("struct") + 7
  626. pos2 = str.find("QString::Null")
  627. if pos1 > -1 and pos2 > -1:
  628. qqNs = str[pos1:pos2]
  629. return qqNs
  630. return ""
  631. except:
  632. return ""
  633. def findFirstZero(p, maximum):
  634. for i in xrange(maximum):
  635. if p.dereference() == 0:
  636. return i
  637. p = p + 1
  638. return maximum + 1
  639. def encodeCArray(p, innerType, suffix):
  640. t = lookupType(innerType)
  641. p = p.cast(t.pointer())
  642. limit = findFirstZero(p, qqStringCutOff)
  643. s = readRawMemory(p, limit * t.sizeof)
  644. if limit > qqStringCutOff:
  645. s += suffix
  646. return s
  647. def encodeCharArray(p):
  648. return encodeCArray(p, "unsigned char", "2e2e2e")
  649. def encodeChar2Array(p):
  650. return encodeCArray(p, "unsigned short", "2e002e002e00")
  651. def encodeChar4Array(p):
  652. return encodeCArray(p, "unsigned int", "2e0000002e0000002e000000")
  653. def qByteArrayData(value):
  654. private = value['d']
  655. checkRef(private['ref'])
  656. try:
  657. # Qt 5. Will fail on Qt 4 due to the missing 'offset' member.
  658. offset = private['offset']
  659. charPointerType = lookupType('char *')
  660. data = private.cast(charPointerType) + private['offset']
  661. return data, int(private['size']), int(private['alloc'])
  662. except:
  663. # Qt 4:
  664. return private['data'], int(private['size']), int(private['alloc'])
  665. def computeLimit(size, limit):
  666. if limit is None:
  667. return size
  668. if limit == 0:
  669. return min(size, qqStringCutOff)
  670. return min(size, limit)
  671. def encodeByteArray(value, limit = None):
  672. data, size, alloc = qByteArrayData(value)
  673. if alloc != 0:
  674. check(0 <= size and size <= alloc and alloc <= 100*1000*1000)
  675. limit = computeLimit(size, limit)
  676. s = readRawMemory(data, limit)
  677. if limit < size:
  678. s += "2e2e2e"
  679. return s
  680. def qStringData(value):
  681. private = value['d']
  682. checkRef(private['ref'])
  683. try:
  684. # Qt 5. Will fail on Qt 4 due to the missing 'offset' member.
  685. offset = private['offset']
  686. ushortPointerType = lookupType('ushort *')
  687. data = private.cast(ushortPointerType) + offset / 2
  688. return data, int(private['size']), int(private['alloc'])
  689. except:
  690. # Qt 4.
  691. return private['data'], int(private['size']), int(private['alloc'])
  692. def encodeString(value, limit = 0):
  693. data, size, alloc = qStringData(value)
  694. if alloc != 0:
  695. check(0 <= size and size <= alloc and alloc <= 100*1000*1000)
  696. limit = computeLimit(size, limit)
  697. s = readRawMemory(data, 2 * limit)
  698. if limit < size:
  699. s += "2e002e002e00"
  700. return s
  701. def stripTypedefs(type):
  702. type = type.unqualified()
  703. while type.code == TypedefCode:
  704. type = type.strip_typedefs().unqualified()
  705. return type
  706. def extractFields(type):
  707. # Insufficient, see http://sourceware.org/bugzilla/show_bug.cgi?id=10953:
  708. #fields = type.fields()
  709. # Insufficient, see http://sourceware.org/bugzilla/show_bug.cgi?id=11777:
  710. #fields = defsype).fields()
  711. # This seems to work.
  712. #warn("TYPE 0: %s" % type)
  713. type = stripTypedefs(type)
  714. fields = type.fields()
  715. if len(fields):
  716. return fields
  717. #warn("TYPE 1: %s" % type)
  718. # This fails for arrays. See comment in lookupType.
  719. type0 = lookupType(str(type))
  720. if not type0 is None:
  721. type = type0
  722. if type.code == FunctionCode:
  723. return []
  724. #warn("TYPE 2: %s" % type)
  725. fields = type.fields()
  726. #warn("FIELDS: %s" % fields)
  727. return fields
  728. #######################################################################
  729. #
  730. # LocalItem
  731. #
  732. #######################################################################
  733. # Contains iname, name, and value.
  734. class LocalItem:
  735. pass
  736. #######################################################################
  737. #
  738. # SetupCommand
  739. #
  740. #######################################################################
  741. # This is a cache mapping from 'type name' to 'display alternatives'.
  742. qqFormats = {}
  743. # This is a cache of all known dumpers.
  744. qqDumpers = {}
  745. # This is a cache of all dumpers that support writing.
  746. qqEditable = {}
  747. # This keeps canonical forms of the typenames, without array indices etc.
  748. qqStripForFormat = {}
  749. def stripForFormat(typeName):
  750. if typeName in qqStripForFormat:
  751. return qqStripForFormat[typeName]
  752. stripped = ""
  753. inArray = 0
  754. for c in stripClassTag(typeName):
  755. if c == '<':
  756. break
  757. if c == ' ':
  758. continue
  759. if c == '[':
  760. inArray += 1
  761. elif c == ']':
  762. inArray -= 1
  763. if inArray and ord(c) >= 48 and ord(c) <= 57:
  764. continue
  765. stripped += c
  766. qqStripForFormat[typeName] = stripped
  767. return stripped
  768. def bbsetup(args):
  769. typeCache = {}
  770. module = sys.modules[__name__]
  771. for key, value in module.__dict__.items():
  772. if key.startswith("qdump__"):
  773. name = key[7:]
  774. qqDumpers[name] = value
  775. qqFormats[name] = qqFormats.get(name, "")
  776. elif key.startswith("qform__"):
  777. name = key[7:]
  778. formats = ""
  779. try:
  780. formats = value()
  781. except:
  782. pass
  783. qqFormats[name] = formats
  784. elif key.startswith("qedit__"):
  785. name = key[7:]
  786. try:
  787. qqEditable[name] = value
  788. except:
  789. pass
  790. result = "dumpers=["
  791. #qqNs = qtNamespace() # This is too early
  792. for key, value in qqFormats.items():
  793. if qqEditable.has_key(key):
  794. result += '{type="%s",formats="%s",editable="true"},' % (key, value)
  795. else:
  796. result += '{type="%s",formats="%s"},' % (key, value)
  797. result += ']'
  798. #result += ',namespace="%s"' % qqNs
  799. result += ',hasInferiorThreadList="%s"' % int(hasInferiorThreadList())
  800. return result
  801. registerCommand("bbsetup", bbsetup)
  802. #######################################################################
  803. #
  804. # Edit Command
  805. #
  806. #######################################################################
  807. def bbedit(args):
  808. (type, expr, value) = args.split(",")
  809. type = base64.b16decode(type, True)
  810. ns = qtNamespace()
  811. if type.startswith(ns):
  812. type = type[len(ns):]
  813. type = type.replace("::", "__")
  814. pos = type.find('<')
  815. if pos != -1:
  816. type = type[0:pos]
  817. expr = base64.b16decode(expr, True)
  818. value = base64.b16decode(value, True)
  819. #warn("EDIT: %s %s %s %s: " % (pos, type, expr, value))
  820. if qqEditable.has_key(type):
  821. qqEditable[type](expr, value)
  822. else:
  823. gdb.execute("set (%s)=%s" % (expr, value))
  824. registerCommand("bbedit", bbedit)
  825. #######################################################################
  826. #
  827. # Frame Command
  828. #
  829. #######################################################################
  830. typesToReport = {}
  831. def bb(args):
  832. global typesToReport
  833. output = Dumper(args).output
  834. output.append('],typeinfo=[')
  835. for name, type in typesToReport.iteritems():
  836. # Happens e.g. for '(anonymous namespace)::InsertDefOperation'
  837. if not type is None:
  838. output.append('{name="%s",size="%s"}'
  839. % (base64.b64encode(name), type.sizeof))
  840. output.append(']')
  841. typesToReport = {}
  842. return "".join(output)
  843. def p1(args):
  844. import cProfile
  845. cProfile.run('bb("%s")' % args, "/tmp/bbprof")
  846. import pstats
  847. pstats.Stats('/tmp/bbprof').sort_stats('time').print_stats()
  848. return ""
  849. def p2(args):
  850. import timeit
  851. return timeit.repeat('bb("%s")' % args,
  852. 'from __main__ import bb', number=10)
  853. registerCommand("bb", bb)
  854. registerCommand("p1", p1)
  855. registerCommand("p2", p2)
  856. #######################################################################
  857. #
  858. # The Dumper Class
  859. #
  860. #######################################################################
  861. class Dumper:
  862. def __init__(self, args):
  863. self.output = []
  864. self.currentIName = ""
  865. self.currentPrintsAddress = True
  866. self.currentChildType = ""
  867. self.currentChildNumChild = -1
  868. self.currentMaxNumChild = -1
  869. self.currentNumChild = -1
  870. self.currentValue = None
  871. self.currentValuePriority = -100
  872. self.currentValueEncoding = None
  873. self.currentType = None
  874. self.currentTypePriority = -100
  875. self.typeformats = {}
  876. self.formats = {}
  877. self.expandedINames = ""
  878. self.output.append('data=[')
  879. options = []
  880. varList = []
  881. watchers = ""
  882. resultVarName = ""
  883. for arg in args.split(' '):
  884. pos = arg.find(":") + 1
  885. if arg.startswith("options:"):
  886. options = arg[pos:].split(",")
  887. elif arg.startswith("vars:"):
  888. if len(arg[pos:]) > 0:
  889. varList = arg[pos:].split(",")
  890. elif arg.startswith("resultvarname:"):
  891. resultVarName = arg[pos:]
  892. elif arg.startswith("expanded:"):
  893. self.expandedINames = set(arg[pos:].split(","))
  894. elif arg.startswith("typeformats:"):
  895. for f in arg[pos:].split(","):
  896. pos = f.find("=")
  897. if pos != -1:
  898. type = base64.b16decode(f[0:pos], True)
  899. self.typeformats[type] = int(f[pos+1:])
  900. elif arg.startswith("formats:"):
  901. for f in arg[pos:].split(","):
  902. pos = f.find("=")
  903. if pos != -1:
  904. self.formats[f[0:pos]] = int(f[pos+1:])
  905. elif arg.startswith("watchers:"):
  906. watchers = base64.b16decode(arg[pos:], True)
  907. self.useDynamicType = "dyntype" in options
  908. self.useFancy = "fancy" in options
  909. self.passExceptions = "pe" in options
  910. self.autoDerefPointers = "autoderef" in options
  911. self.partialUpdate = "partial" in options
  912. self.tooltipOnly = "tooltiponly" in options
  913. self.noLocals = "nolocals" in options
  914. self.ns = qtNamespace()
  915. #warn("NAMESPACE: '%s'" % self.ns)
  916. #warn("VARIABLES: %s" % varList)
  917. #warn("EXPANDED INAMES: %s" % self.expandedINames)
  918. #warn("WATCHERS: %s" % watchers)
  919. #warn("PARTIAL: %s" % self.partialUpdate)
  920. #warn("NO LOCALS: %s" % self.noLocals)
  921. module = sys.modules[__name__]
  922. #
  923. # Locals
  924. #
  925. locals = []
  926. fullUpdateNeeded = True
  927. if self.partialUpdate and len(varList) == 1 and not self.tooltipOnly:
  928. #warn("PARTIAL: %s" % varList)
  929. parts = varList[0].split('.')
  930. #warn("PARTIAL PARTS: %s" % parts)
  931. name = parts[1]
  932. #warn("PARTIAL VAR: %s" % name)
  933. #fullUpdateNeeded = False
  934. try:
  935. frame = gdb.selected_frame()
  936. item = LocalItem()
  937. item.iname = "local." + name
  938. item.name = name
  939. item.value = frame.read_var(name)
  940. locals = [item]
  941. #warn("PARTIAL LOCALS: %s" % locals)
  942. fullUpdateNeeded = False
  943. except:
  944. pass
  945. varList = []
  946. if fullUpdateNeeded and not self.tooltipOnly and not self.noLocals:
  947. locals = listOfLocals(varList)
  948. if "autotest" in options:
  949. for item in listOfLocals([]):
  950. self.expandedINames.add(item.iname)
  951. self.expandedINames.discard("")
  952. #warn("EXPANDED: %s" % self.expandedINames)
  953. # Take care of the return value of the last function call.
  954. if len(resultVarName) > 0:
  955. try:
  956. item = LocalItem()
  957. item.name = resultVarName
  958. item.iname = "return." + resultVarName
  959. item.value = parseAndEvaluate(resultVarName)
  960. locals.append(item)
  961. except:
  962. # Don't bother. It's only supplementary information anyway.
  963. pass
  964. for item in locals:
  965. value = downcast(item.value) if self.useDynamicType else item.value
  966. with OutputSafer(self):
  967. self.anonNumber = -1
  968. type = value.type.unqualified()
  969. typeName = str(type)
  970. # Special handling for char** argv.
  971. if type.code == PointerCode \
  972. and item.iname == "local.argv" \
  973. and typeName == "char **":
  974. n = 0
  975. p = value
  976. # p is 0 for "optimized out" cases. Or contains rubbish.
  977. try:
  978. if not isNull(p):
  979. while not isNull(p.dereference()) and n <= 100:
  980. p += 1
  981. n += 1
  982. except:
  983. pass
  984. with TopLevelItem(self, item.iname):
  985. self.put('iname="local.argv",name="argv",')
  986. self.putItemCount(n, 100)
  987. self.putType(typeName)
  988. self.putNumChild(n)
  989. if self.currentIName in self.expandedINames:
  990. p = value
  991. with Children(self, n):
  992. for i in xrange(n):
  993. self.putSubItem(i, p.dereference())
  994. p += 1
  995. continue
  996. else:
  997. # A "normal" local variable or parameter.
  998. with TopLevelItem(self, item.iname):
  999. self.put('iname="%s",' % item.iname)
  1000. self.put('name="%s",' % item.name)
  1001. self.putItem(value)
  1002. #
  1003. # Watchers
  1004. #
  1005. with OutputSafer(self):
  1006. if len(watchers) > 0:
  1007. self.put(",")
  1008. for watcher in watchers.split("##"):
  1009. (exp, iname) = watcher.split("#")
  1010. self.handleWatch(exp, iname)
  1011. #print('data=[' + locals + sep + watchers + ']\n')
  1012. def handleWatch(self, exp, iname):
  1013. exp = str(exp)
  1014. escapedExp = base64.b64encode(exp);
  1015. #warn("HANDLING WATCH %s, INAME: '%s'" % (exp, iname))
  1016. if exp.startswith("[") and exp.endswith("]"):
  1017. #warn("EVAL: EXP: %s" % exp)
  1018. with TopLevelItem(self, iname):
  1019. self.put('iname="%s",' % iname)
  1020. self.put('wname="%s",' % escapedExp)
  1021. try:
  1022. list = eval(exp)
  1023. self.putValue("")
  1024. self.putNoType()
  1025. self.putNumChild(len(list))
  1026. # This is a list of expressions to evaluate
  1027. with Children(self, len(list)):
  1028. itemNumber = 0
  1029. for item in list:
  1030. self.handleWatch(item, "%s.%d" % (iname, itemNumber))
  1031. itemNumber += 1
  1032. except RuntimeError, error:
  1033. warn("EVAL: ERROR CAUGHT %s" % error)
  1034. self.putValue("<syntax error>")
  1035. self.putNoType()
  1036. self.putNumChild(0)
  1037. self.put("children=[],")
  1038. return
  1039. with TopLevelItem(self, iname):
  1040. self.put('iname="%s",' % iname)
  1041. self.put('wname="%s",' % escapedExp)
  1042. if len(exp) == 0: # The <Edit> case
  1043. self.putValue(" ")
  1044. self.putNoType()
  1045. self.putNumChild(0)
  1046. else:
  1047. try:
  1048. value = parseAndEvaluate(exp)
  1049. self.putItem(value)
  1050. except RuntimeError:
  1051. self.currentType = " "
  1052. self.currentValue = "<no such value>"
  1053. self.currentChildNumChild = -1
  1054. self.currentNumChild = 0
  1055. self.putNumChild(0)
  1056. def put(self, value):
  1057. self.output.append(value)
  1058. def putField(self, name, value):
  1059. self.put('%s="%s",' % (name, value))
  1060. def childRange(self):
  1061. if self.currentMaxNumChild is None:
  1062. return xrange(0, self.currentNumChild)
  1063. return xrange(min(self.currentMaxNumChild, self.currentNumChild))
  1064. # Convenience function.
  1065. def putItemCount(self, count, maximum = 1000000000):
  1066. # This needs to override the default value, so don't use 'put' directly.
  1067. if count > maximum:
  1068. self.putValue('<>%s items>' % maximum)
  1069. else:
  1070. self.putValue('<%s items>' % count)
  1071. def putType(self, type, priority = 0):
  1072. # Higher priority values override lower ones.
  1073. if priority >= self.currentTypePriority:
  1074. self.currentType = str(type)
  1075. self.currentTypePriority = priority
  1076. def putNoType(self):
  1077. # FIXME: replace with something that does not need special handling
  1078. # in SubItem.__exit__().
  1079. self.putBetterType(" ")
  1080. def putInaccessible(self):
  1081. #self.putBetterType(" ")
  1082. self.putNumChild(0)
  1083. self.currentValue = None
  1084. def putBetterType(self, type, priority = 0):
  1085. self.currentType = str(type)
  1086. self.currentTypePriority = self.currentTypePriority + 1
  1087. def putAddress(self, addr):
  1088. if self.currentPrintsAddress:
  1089. try:
  1090. # addr can be "None", long(None) fails.
  1091. self.put('addr="0x%x",' % long(addr))
  1092. except:
  1093. pass
  1094. def putNumChild(self, numchild):
  1095. #warn("NUM CHILD: '%s' '%s'" % (numchild, self.currentChildNumChild))
  1096. if numchild != self.currentChildNumChild:
  1097. self.put('numchild="%s",' % numchild)
  1098. def putValue(self, value, encoding = None, priority = 0):
  1099. # Higher priority values override lower ones.
  1100. if priority >= self.currentValuePriority:
  1101. self.currentValue = value
  1102. self.currentValuePriority = priority
  1103. self.currentValueEncoding = encoding
  1104. def putPointerValue(self, value):
  1105. # Use a lower priority
  1106. if value is None:
  1107. self.putValue(" ", None, -1)
  1108. else:
  1109. self.putValue("0x%x" % value.dereference().cast(
  1110. lookupType("unsigned long")), None, -1)
  1111. def putStringValue(self, value, priority = 0):
  1112. if not value is None:
  1113. str = encodeString(value)
  1114. self.putValue(str, Hex4EncodedLittleEndian, priority)
  1115. def putDisplay(self, format, value = None, cmd = None):
  1116. self.put('editformat="%s",' % format)
  1117. if cmd is None:
  1118. if not value is None:
  1119. self.put('editvalue="%s",' % value)
  1120. else:
  1121. self.put('editvalue="%s|%s",' % (cmd, value))
  1122. def putByteArrayValue(self, value):
  1123. str = encodeByteArray(value)
  1124. self.putValue(str, Hex2EncodedLatin1)
  1125. def putName(self, name):
  1126. self.put('name="%s",' % name)
  1127. def putMapName(self, value):
  1128. ns = qtNamespace()
  1129. if str(value.type) == ns + "QString":
  1130. self.put('key="%s",' % encodeString(value))
  1131. self.put('keyencoded="%s",' % Hex4EncodedLittleEndian)
  1132. elif str(value.type) == ns + "QByteArray":
  1133. self.put('key="%s",' % encodeByteArray(value))
  1134. self.put('keyencoded="%s",' % Hex2EncodedLatin1)
  1135. else:
  1136. self.put('name="%s",' % value)
  1137. def isExpanded(self):
  1138. #warn("IS EXPANDED: %s in %s: %s" % (self.currentIName,
  1139. # self.expandedINames, self.currentIName in self.expandedINames))
  1140. return self.currentIName in self.expandedINames
  1141. def isExpandedSubItem(self, component):
  1142. iname = "%s.%s" % (self.currentIName, component)
  1143. #warn("IS EXPANDED: %s in %s" % (iname, self.expandedINames))
  1144. return iname in self.expandedINames
  1145. def stripNamespaceFromType(self, typeName):
  1146. type = stripClassTag(typeName)
  1147. if len(self.ns) > 0 and type.startswith(self.ns):
  1148. type = type[len(self.ns):]
  1149. pos = type.find("<")
  1150. # FIXME: make it recognize foo<A>::bar<B>::iterator?
  1151. while pos != -1:
  1152. pos1 = type.rfind(">", pos)
  1153. type = type[0:pos] + type[pos1+1:]
  1154. pos = type.find("<")
  1155. return type
  1156. def isMovableType(self, type):
  1157. if type.code == PointerCode:
  1158. return True
  1159. if isSimpleType(type):
  1160. return True
  1161. return self.stripNamespaceFromType(str(type)) in movableTypes
  1162. def putIntItem(self, name, value):
  1163. with SubItem(self, name):
  1164. self.putValue(value)
  1165. self.putAddress(value.address)
  1166. self.putType("int")
  1167. self.putNumChild(0)
  1168. def putBoolItem(self, name, value):
  1169. with SubItem(self, name):
  1170. self.putValue(value)
  1171. self.putType("bool")
  1172. self.putNumChild(0)
  1173. def currentItemFormat(self):
  1174. format = self.formats.get(self.currentIName)
  1175. if format is None:
  1176. format = self.typeformats.get(stripForFormat(str(self.currentType)))
  1177. return format
  1178. def putSubItem(self, component, value, tryDynamic=True):
  1179. with SubItem(self, component):
  1180. self.putItem(value, tryDynamic)
  1181. def putNamedSubItem(self, component, value, name):
  1182. with SubItem(self, component):
  1183. self.putName(name)
  1184. self.putItem(value)
  1185. def tryPutArrayContents(self, typeobj, base, n):
  1186. if not isSimpleType(typeobj):
  1187. return False
  1188. size = n * typeobj.sizeof;
  1189. self.put('childtype="%s",' % typeobj)
  1190. self.put('addrbase="0x%x",' % long(base))
  1191. self.put('addrstep="0x%x",' % long(typeobj.sizeof))
  1192. self.put('arrayencoding="%s",' % simpleEncoding(typeobj))
  1193. self.put('arraydata="')
  1194. self.put(readRawMemory(base, size))
  1195. self.put('",')
  1196. return True
  1197. def putPlotData(self, type, base, n, plotFormat):
  1198. if self.isExpanded():
  1199. self.putArrayData(type, base, n)
  1200. if not hasPlot():
  1201. return
  1202. if not isSimpleType(type):
  1203. self.putValue(self.currentValue + " (not plottable)")
  1204. return
  1205. global gnuplotPipe
  1206. global gnuplotPid
  1207. format = self.currentItemFormat()
  1208. iname = self.currentIName
  1209. #if False:
  1210. if format != plotFormat:
  1211. if iname in gnuplotPipe:
  1212. os.kill(gnuplotPid[iname], 9)
  1213. del gnuplotPid[iname]
  1214. gnuplotPipe[iname].terminate()
  1215. del gnuplotPipe[iname]
  1216. return
  1217. base = base.cast(type.pointer())
  1218. if not iname in gnuplotPipe:
  1219. gnuplotPipe[iname] = subprocess.Popen(["gnuplot"],
  1220. stdin=subprocess.PIPE)
  1221. gnuplotPid[iname] = gnuplotPipe[iname].pid
  1222. f = gnuplotPipe[iname].stdin;
  1223. f.write("set term wxt noraise\n")
  1224. f.write("set title 'Data fields'\n")
  1225. f.write("set xlabel 'Index'\n")
  1226. f.write("set ylabel 'Value'\n")
  1227. f.write("set grid\n")
  1228. f.write("set style data lines;\n")
  1229. f.write("plot '-' title '%s'\n" % iname)
  1230. for i in range(1, n):
  1231. f.write(" %s\n" % base.dereference())
  1232. base += 1
  1233. f.write("e\n")
  1234. def putArrayData(self, type, base, n,
  1235. childNumChild = None, maxNumChild = 10000):
  1236. base = base.cast(type.pointer())
  1237. if not self.tryPutArrayContents(type, base, n):
  1238. with Children(self, n, type, childNumChild, maxNumChild,
  1239. base, type.sizeof):
  1240. for i in self.childRange():
  1241. self.putSubItem(i, (base + i).dereference())
  1242. def putCallItem(self, name, value, func, *args):
  1243. result = call2(value, func, args)
  1244. with SubItem(self, name):
  1245. self.putItem(result)
  1246. def putItem(self, value, tryDynamic=True):
  1247. if value is None:
  1248. # Happens for non-available watchers in gdb versions that
  1249. # need to use gdb.execute instead of gdb.parse_and_eval
  1250. self.putValue("<not available>")
  1251. self.putType("<unknown>")
  1252. self.putNumChild(0)
  1253. return
  1254. type = value.type.unqualified()
  1255. typeName = str(type)
  1256. tryDynamic &= self.useDynamicType
  1257. lookupType(typeName) # Fill type cache
  1258. # FIXME: Gui shows references stripped?
  1259. #warn(" ")
  1260. #warn("REAL INAME: %s " % self.currentIName)
  1261. #warn("REAL TYPE: %s " % value.type)
  1262. #warn("REAL CODE: %s " % value.type.code)
  1263. #warn("REAL VALUE: %s " % value)
  1264. if type.code == ReferenceCode:
  1265. try:
  1266. # Try to recognize null references explicitly.
  1267. if long(value.address) == 0:
  1268. self.putValue("<null reference>")
  1269. self.putType(typeName)
  1270. self.putNumChild(0)
  1271. return
  1272. except:
  1273. pass
  1274. if tryDynamic:
  1275. try:
  1276. # Dynamic references are not supported by gdb, see
  1277. # http://sourceware.org/bugzilla/show_bug.cgi?id=14077.
  1278. # Find the dynamic type manually using referenced_type.
  1279. value = value.referenced_value()
  1280. value = value.cast(value.dynamic_type)
  1281. self.putItem(value)
  1282. self.putBetterType("%s &" % value.type)
  1283. return
  1284. except:
  1285. pass
  1286. try:
  1287. # FIXME: This throws "RuntimeError: Attempt to dereference a
  1288. # generic pointer." with MinGW's gcc 4.5 when it "identifies"
  1289. # a "QWidget &" as "void &" and with optimized out code.
  1290. self.putItem(value.cast(type.target().unqualified()))
  1291. self.putBetterType(typeName)
  1292. return
  1293. except RuntimeError:
  1294. self.putValue("<optimized out reference>")
  1295. self.putType(typeName)
  1296. self.putNumChild(0)
  1297. return
  1298. if type.code == IntCode or type.code == CharCode:
  1299. self.putAddress(value.address)
  1300. self.putType(typeName)
  1301. if value.is_optimized_out:
  1302. self.putValue("<optimized out>")
  1303. else:
  1304. self.putValue(value)
  1305. self.putNumChild(0)
  1306. return
  1307. if type.code == FloatCode or type.code == BoolCode:
  1308. self.putAddress(value.address)
  1309. self.putType(typeName)
  1310. if value.is_optimized_out:
  1311. self.putValue("<optimized out>")
  1312. else:
  1313. self.putValue(value)
  1314. self.putNumChild(0)
  1315. return
  1316. if type.code == EnumCode:
  1317. self.putAddress(value.address)
  1318. self.putType(typeName)
  1319. if value.is_optimized_out:
  1320. self.putValue("<optimized out>")
  1321. else:
  1322. self.putValue("%s (%d)" % (value, value))
  1323. self.putNumChild(0)
  1324. return
  1325. if type.code == ComplexCode:
  1326. self.putAddress(value.address)
  1327. self.putType(typeName)
  1328. if value.is_optimized_out:
  1329. self.putValue("<optimized out>")
  1330. else:
  1331. self.putValue("%s" % value)
  1332. self.putNumChild(0)
  1333. return
  1334. if type.code == TypedefCode:
  1335. if typeName in qqDumpers:
  1336. self.putType(typeName)
  1337. qqDumpers[typeName](self, value)
  1338. return
  1339. type = stripTypedefs(type)
  1340. # The cast can destroy the address?
  1341. self.putAddress(value.address)
  1342. # Workaround for http://sourceware.org/bugzilla/show_bug.cgi?id=13380
  1343. if type.code == ArrayCode:
  1344. value = parseAndEvaluate("{%s}%s" % (type, value.address))
  1345. else:
  1346. try:
  1347. value = value.cast(type)
  1348. except:
  1349. self.putValue("<optimized out typedef>")
  1350. self.putType(typeName)
  1351. self.putNumChild(0)
  1352. return
  1353. self.putItem(value)
  1354. self.putBetterType(typeName)
  1355. return
  1356. if type.code == ArrayCode:
  1357. qdump____c_style_array__(self, value)
  1358. return
  1359. if type.code == PointerCode:
  1360. #warn("POINTER: %s" % value)

Large files files are truncated, but you can click here to view the full file