gpt4 book ai didi

GDB 初始化文件 .gdbinit 中的 Python 代码

转载 作者:太空狗 更新时间:2023-10-30 00:50:56 25 4
gpt4 key购买 nike

我正在尝试创建一个 ~/.gdbinit,其中包含一些用于各种 Qt 对象的 Qt pretty-print ,尤其是 QString。我想在没有 Qt Creator 的情况下使用常规 GDB 来执行此操作。这是我放入文件中的内容(此脚本是我在 Niko's Blog 处修改的 scipts 形式):

# -*- coding: iso-8859-1 -*-
# Pretty-printers for Qt4.

# Copyright (C) 2009 Niko Sams <niko.sams@gmail.com>

# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

import gdb
import itertools
import re
import sys

class QStringPrinter:

def __init__(self, val):
self.val = val

def to_string(self):
#ret = ""
#i = 0
size = self.val['d']['size']
#while i < size:
# char = self.val['d']['data'][i]
# if (char > 127):
# ret += "\\u%x" % int(char)
# else:
# ret += chr(char)
# i = i + 1
#return ret
dataAsCharPointer = self.val['d']['data'].cast(gdb.lookup_type("char").pointer())
return dataAsCharPointer.string(encoding = 'UTF-16', length = size * 2)

def display_hint (self):
return 'string'


class QByteArrayPrinter:

def __init__(self, val):
self.val = val

class _iterator:
def __init__(self, data, size):
self.data = data
self.size = size
self.count = 0

def __iter__(self):
return self

def next(self):
if self.count >= self.size:
raise StopIteration
count = self.count
self.count = self.count + 1
return ('[%d]' % count, self.data[count])

def children(self):
return self._iterator(self.val['d']['data'], self.val['d']['size'])

def to_string(self):
#todo: handle charset correctly
return self.val['d']['data'].string()

def display_hint (self):
return 'string'

class QListPrinter:
"Print a QList"

class _iterator:
def __init__(self, nodetype, d):
self.nodetype = nodetype
self.d = d
self.count = 0

def __iter__(self):
return self

def next(self):
if self.count >= self.d['end'] - self.d['begin']:
raise StopIteration
count = self.count
array = self.d['array'][self.d['begin'] + count]

#from QTypeInfo::isLarge
isLarge = self.nodetype.sizeof > gdb.lookup_type('void').pointer().sizeof

#isStatic is not needed anymore since Qt 4.6
#isPointer = self.nodetype.code == gdb.TYPE_CODE_PTR
#
##unfortunately we can't use QTypeInfo<T>::isStatic as it's all inlined, so use
##this list of types that use Q_DECLARE_TYPEINFO(T, Q_MOVABLE_TYPE)
##(obviously it won't work for custom types)
#movableTypes = ['QRect', 'QRectF', 'QString', 'QMargins', 'QLocale', 'QChar', 'QDate', 'QTime', 'QDateTime', 'QVector',
# 'QRegExpr', 'QPoint', 'QPointF', 'QByteArray', 'QSize', 'QSizeF', 'QBitArray', 'QLine', 'QLineF', 'QModelIndex', 'QPersitentModelIndex',
# 'QVariant', 'QFileInfo', 'QUrl', 'QXmlStreamAttribute', 'QXmlStreamNamespaceDeclaration', 'QXmlStreamNotationDeclaration',
# 'QXmlStreamEntityDeclaration']
#if movableTypes.count(self.nodetype.tag):
# isStatic = False
#else:
# isStatic = not isPointer
isStatic = False

if isLarge or isStatic: #see QList::Node::t()
node = array.cast(gdb.lookup_type('QList<%s>::Node' % self.nodetype).pointer())
else:
node = array.cast(gdb.lookup_type('QList<%s>::Node' % self.nodetype))
self.count = self.count + 1
return ('[%d]' % count, node['v'].cast(self.nodetype))

def __init__(self, val, container, itype):
self.val = val
self.container = container
if itype == None:
self.itype = self.val.type.template_argument(0)
else:
self.itype = gdb.lookup_type(itype)

def children(self):
return self._iterator(self.itype, self.val['d'])

def to_string(self):
if self.val['d']['end'] == self.val['d']['begin']:
empty = "empty "
else:
empty = ""

return "%s%s<%s>" % ( empty, self.container, self.itype )

class QVectorPrinter:
"Print a QVector"

class _iterator:
def __init__(self, nodetype, d, p):
self.nodetype = nodetype
self.d = d
self.p = p
self.count = 0

def __iter__(self):
return self

def next(self):
if self.count >= self.p['size']:
raise StopIteration
count = self.count

self.count = self.count + 1
return ('[%d]' % count, self.p['array'][count])

def __init__(self, val, container):
self.val = val
self.container = container
self.itype = self.val.type.template_argument(0)

def children(self):
return self._iterator(self.itype, self.val['d'], self.val['p'])

def to_string(self):
if self.val['d']['size'] == 0:
empty = "empty "
else:
empty = ""

return "%s%s<%s>" % ( empty, self.container, self.itype )

class QLinkedListPrinter:
"Print a QLinkedList"

class _iterator:
def __init__(self, nodetype, begin, size):
self.nodetype = nodetype
self.it = begin
self.pos = 0
self.size = size

def __iter__(self):
return self

def next(self):
if self.pos >= self.size:
raise StopIteration

pos = self.pos
val = self.it['t']
self.it = self.it['n']
self.pos = self.pos + 1
return ('[%d]' % pos, val)

def __init__(self, val):
self.val = val
self.itype = self.val.type.template_argument(0)

def children(self):
return self._iterator(self.itype, self.val['e']['n'], self.val['d']['size'])

def to_string(self):
if self.val['d']['size'] == 0:
empty = "empty "
else:
empty = ""

return "%sQLinkedList<%s>" % ( empty, self.itype )

class QMapPrinter:
"Print a QMap"

class _iterator:
def __init__(self, val):
self.val = val
self.ktype = self.val.type.template_argument(0)
self.vtype = self.val.type.template_argument(1)
self.data_node = self.val['e']['forward'][0]
self.count = 0

def __iter__(self):
return self

def payload (self):

#we can't use QMapPayloadNode as it's inlined
#as a workaround take the sum of sizeof(members)
ret = self.ktype.sizeof
ret += self.vtype.sizeof
ret += gdb.lookup_type('void').pointer().sizeof

#but because of data alignment the value can be higher
#so guess it's aliged by sizeof(void*)
#TODO: find a real solution for this problem
ret += ret % gdb.lookup_type('void').pointer().sizeof

ret -= gdb.lookup_type('void').pointer().sizeof
return ret

def concrete (self, data_node):
node_type = gdb.lookup_type('QMapNode<%s, %s>' % (self.ktype, self.vtype)).pointer()
return (data_node.cast(gdb.lookup_type('char').pointer()) - self.payload()).cast(node_type)

def next(self):
if self.data_node == self.val['e']:
raise StopIteration
node = self.concrete(self.data_node).dereference()
if self.count % 2 == 0:
item = node['key']
else:
item = node['value']
self.data_node = node['forward'][0]

result = ('[%d]' % self.count, item)
self.count = self.count + 1
return result


def __init__(self, val, container):
self.val = val
self.container = container

def children(self):
return self._iterator(self.val)

def to_string(self):
if self.val['d']['size'] == 0:
empty = "empty "
else:
empty = ""

return "%s%s<%s, %s>" % ( empty, self.container, self.val.type.template_argument(0), self.val.type.template_argument(1) )

def display_hint (self):
return 'map'

class QHashPrinter:
"Print a QHash"

class _iterator:
def __init__(self, val):
self.val = val
self.d = self.val['d']
self.ktype = self.val.type.template_argument(0)
self.vtype = self.val.type.template_argument(1)
self.end_node = self.d.cast(gdb.lookup_type('QHashData::Node').pointer())
self.data_node = self.firstNode()
self.count = 0

def __iter__(self):
return self

def hashNode (self):
"Casts the current QHashData::Node to a QHashNode and returns the result. See also QHash::concrete()"
return self.data_node.cast(gdb.lookup_type('QHashNode<%s, %s>' % (self.ktype, self.vtype)).pointer())

def firstNode (self):
"Get the first node, See QHashData::firstNode()."
e = self.d.cast(gdb.lookup_type('QHashData::Node').pointer())
#print "QHashData::firstNode() e %s" % e
bucketNum = 0
bucket = self.d['buckets'][bucketNum]
#print "QHashData::firstNode() *bucket %s" % bucket
n = self.d['numBuckets']
#print "QHashData::firstNode() n %s" % n
while n:
#print "QHashData::firstNode() in while, n %s" % n;
if bucket != e:
#print "QHashData::firstNode() in while, return *bucket %s" % bucket
return bucket
bucketNum += 1
bucket = self.d['buckets'][bucketNum]
#print "QHashData::firstNode() in while, new bucket %s" % bucket
n -= 1
#print "QHashData::firstNode() return e %s" % e
return e


def nextNode (self, node):
"Get the nextNode after the current, see also QHashData::nextNode()."
#print "******************************** nextNode"
#print "nextNode: node %s" % node
next = node['next'].cast(gdb.lookup_type('QHashData::Node').pointer())
e = next

#print "nextNode: next %s" % next
if next['next']:
#print "nextNode: return next"
return next

#print "nextNode: node->h %s" % node['h']
#print "nextNode: numBuckets %s" % self.d['numBuckets']
start = (node['h'] % self.d['numBuckets']) + 1
bucketNum = start
#print "nextNode: start %s" % start
bucket = self.d['buckets'][start]
#print "nextNode: bucket %s" % bucket
n = self.d['numBuckets'] - start
#print "nextNode: n %s" % n
while n:
#print "nextNode: in while; n %s" % n
#print "nextNode: in while; e %s" % e
#print "nextNode: in while; *bucket %s" % bucket
if bucket != e:
#print "nextNode: in while; return bucket %s" % bucket
return bucket
bucketNum += 1
bucket = self.d['buckets'][bucketNum]
n -= 1
#print "nextNode: return e %s" % e
return e

def next(self):
"GDB iteration, first call returns key, second value and then jumps to the next hash node."
if self.data_node == self.end_node:
raise StopIteration

node = self.hashNode()

if self.count % 2 == 0:
item = node['key']
else:
item = node['value']
self.data_node = self.nextNode(self.data_node)

self.count = self.count + 1
return ('[%d]' % self.count, item)

def __init__(self, val, container):
self.val = val
self.container = container

def children(self):
return self._iterator(self.val)

def to_string(self):
if self.val['d']['size'] == 0:
empty = "empty "
else:
empty = ""

return "%s%s<%s, %s>" % ( empty, self.container, self.val.type.template_argument(0), self.val.type.template_argument(1) )

def display_hint (self):
return 'map'

class QDatePrinter:

def __init__(self, val):
self.val = val

def to_string(self):
julianDay = self.val['jd']

if julianDay == 0:
return "invalid QDate"

# Copied from Qt sources
if julianDay >= 2299161:
# Gregorian calendar starting from October 15, 1582
# This algorithm is from Henry F. Fliegel and Thomas C. Van Flandern
ell = julianDay + 68569;
n = (4 * ell) / 146097;
ell = ell - (146097 * n + 3) / 4;
i = (4000 * (ell + 1)) / 1461001;
ell = ell - (1461 * i) / 4 + 31;
j = (80 * ell) / 2447;
d = ell - (2447 * j) / 80;
ell = j / 11;
m = j + 2 - (12 * ell);
y = 100 * (n - 49) + i + ell;
else:
# Julian calendar until October 4, 1582
# Algorithm from Frequently Asked Questions about Calendars by Claus Toendering
julianDay += 32082;
dd = (4 * julianDay + 3) / 1461;
ee = julianDay - (1461 * dd) / 4;
mm = ((5 * ee) + 2) / 153;
d = ee - (153 * mm + 2) / 5 + 1;
m = mm + 3 - 12 * (mm / 10);
y = dd - 4800 + (mm / 10);
if y <= 0:
--y;
return "%d-%02d-%02d" % (y, m, d)

class QTimePrinter:

def __init__(self, val):
self.val = val

def to_string(self):
ds = self.val['mds']

if ds == -1:
return "invalid QTime"

MSECS_PER_HOUR = 3600000
SECS_PER_MIN = 60
MSECS_PER_MIN = 60000

hour = ds / MSECS_PER_HOUR
minute = (ds % MSECS_PER_HOUR) / MSECS_PER_MIN
second = (ds / 1000)%SECS_PER_MIN
msec = ds % 1000
return "%02d:%02d:%02d.%03d" % (hour, minute, second, msec)

class QDateTimePrinter:

def __init__(self, val):
self.val = val

def to_string(self):
#val['d'] is a QDateTimePrivate, but for some reason casting to that doesn't work
#so work around by manually adjusting the pointer
date = self.val['d'].cast(gdb.lookup_type('char').pointer());
date += gdb.lookup_type('int').sizeof #increment for QAtomicInt ref;
date = date.cast(gdb.lookup_type('QDate').pointer()).dereference();

time = self.val['d'].cast(gdb.lookup_type('char').pointer());
time += gdb.lookup_type('int').sizeof + gdb.lookup_type('QDate').sizeof #increment for QAtomicInt ref; and QDate date;
time = time.cast(gdb.lookup_type('QTime').pointer()).dereference();
return "%s %s" % (date, time)

class QUrlPrinter:

def __init__(self, val):
self.val = val

def to_string(self):
try:
return self.val['d']['encodedOriginal']
except RuntimeError, error:
#if no debug information is avaliable for Qt, try guessing the correct address for encodedOriginal
#problem with this is that if QUrlPrivate members get changed, this fails
offset = gdb.lookup_type('int').sizeof
offset += offset % gdb.lookup_type('void').pointer().sizeof #alignment
offset += gdb.lookup_type('QString').sizeof * 6
offset += gdb.lookup_type('QByteArray').sizeof
encodedOriginal = self.val['d'].cast(gdb.lookup_type('char').pointer());
encodedOriginal += offset
encodedOriginal = encodedOriginal.cast(gdb.lookup_type('QByteArray').pointer()).dereference();
encodedOriginal = encodedOriginal['d']['data'].string()
return encodedOriginal

class QSetPrinter:
"Print a QSet"

def __init__(self, val):
self.val = val

class _iterator:
def __init__(self, hashIterator):
self.hashIterator = hashIterator
self.count = 0

def __iter__(self):
return self

def next(self):
if self.hashIterator.data_node == self.hashIterator.end_node:
raise StopIteration

node = self.hashIterator.hashNode()

item = node['key']
self.hashIterator.data_node = self.hashIterator.nextNode(self.hashIterator.data_node)

self.count = self.count + 1
return ('[%d]' % (self.count-1), item)

def children(self):
hashPrinter = QHashPrinter(self.val['q_hash'], None)
hashIterator = hashPrinter._iterator(self.val['q_hash'])
return self._iterator(hashIterator)

def to_string(self):
if self.val['q_hash']['d']['size'] == 0:
empty = "empty "
else:
empty = ""

return "%sQSet<%s>" % ( empty , self.val.type.template_argument(0) )


class QCharPrinter:

def __init__(self, val):
self.val = val

def to_string(self):
return unichr(self.val['ucs'])

def display_hint (self):
return 'string'

def register_qt4_printers (obj):
if obj == None:
obj = gdb

obj.pretty_printers.append (lookup_function)

def lookup_function (val):
"Look-up and return a pretty-printer that can print val."

# Get the type.
type = val.type;

# If it points to a reference, get the reference.
if type.code == gdb.TYPE_CODE_REF:
type = type.target ()

# Get the unqualified type, stripped of typedefs.
type = type.unqualified ().strip_typedefs ()

# Get the type name.
typename = type.tag
if typename == None:
return None

# Iterate over local dictionary of types to determine
# if a printer is registered for that type. Return an
# instantiation of the printer if found.
for function in pretty_printers_dict:
if function.search (typename):
return pretty_printers_dict[function] (val)

# Cannot find a pretty printer. Return None.
return None

def build_dictionary ():
pretty_printers_dict[re.compile('^QString$')] = lambda val: QStringPrinter(val)
pretty_printers_dict[re.compile('^QByteArray$')] = lambda val: QByteArrayPrinter(val)
pretty_printers_dict[re.compile('^QList<.*>$')] = lambda val: QListPrinter(val, 'QList', None)
pretty_printers_dict[re.compile('^QStringList$')] = lambda val: QListPrinter(val, 'QStringList', 'QString')
pretty_printers_dict[re.compile('^QQueue')] = lambda val: QListPrinter(val, 'QQueue', None)
pretty_printers_dict[re.compile('^QVector<.*>$')] = lambda val: QVectorPrinter(val, 'QVector')
pretty_printers_dict[re.compile('^QStack<.*>$')] = lambda val: QVectorPrinter(val, 'QStack')
pretty_printers_dict[re.compile('^QLinkedList<.*>$')] = lambda val: QLinkedListPrinter(val)
pretty_printers_dict[re.compile('^QMap<.*>$')] = lambda val: QMapPrinter(val, 'QMap')
pretty_printers_dict[re.compile('^QMultiMap<.*>$')] = lambda val: QMapPrinter(val, 'QMultiMap')
pretty_printers_dict[re.compile('^QHash<.*>$')] = lambda val: QHashPrinter(val, 'QHash')
pretty_printers_dict[re.compile('^QMultiHash<.*>$')] = lambda val: QHashPrinter(val, 'QMultiHash')
pretty_printers_dict[re.compile('^QDate$')] = lambda val: QDatePrinter(val)
pretty_printers_dict[re.compile('^QTime$')] = lambda val: QTimePrinter(val)
pretty_printers_dict[re.compile('^QDateTime$')] = lambda val: QDateTimePrinter(val)
pretty_printers_dict[re.compile('^QUrl$')] = lambda val: QUrlPrinter(val)
pretty_printers_dict[re.compile('^QSet<.*>$')] = lambda val: QSetPrinter(val)
pretty_printers_dict[re.compile('^QChar$')] = lambda val: QCharPrinter(val)


pretty_printers_dict = {}

build_dictionary ()

register_qt4_printers (None)

end
set print pretty 1

当我启动 GDB 时,出现以下错误:

GNU gdb (GDB) Fedora (7.4.50.20120120-54.fc17)
<!-- Standard GPL message -->
This GDB was configured as "x86_64-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
/home/ben/.gdbinit:19: Error in sourced command file:
Undefined command: "import". Try "help".

它似乎在第一个 import 语句处失败。我做错了什么?

编辑:

我尝试将 #!/usr/bin/python 添加为第一行,但没有任何区别。失败并出现相同的错误。这是我执行 which python

时得到的位置

最佳答案

您还没有调用 python,只需将 python 添加到文件的开头即可。记住这个脚本只是在 GDB shell 中执行,它不知道它应该被 python 解释器解析,除非你告诉它。

例如,这是我的开始和结束:

python
import sys
sys.path.insert(0, '/home/cmannett85/PrettyPrinters')

...

end

关于GDB 初始化文件 .gdbinit 中的 Python 代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16553283/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com