PageRenderTime 44ms CodeModel.GetById 7ms RepoModel.GetById 0ms app.codeStats 0ms

/share/qtcreator/dumper/dumper.py

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

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