- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我正在尝试创建一个 ~/.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/
当我开始使用 gdb 进行调试时,我将一些断点和命令编辑到 gdbinit 文件中。 如何在不脱离进程的情况下进行调试时更改此文件并再次加载它? 最佳答案 How can I change this
这可能吗? 为了举一个具体的例子,请考虑以下宏: define pos po ([self $arg0]) end 所以现在如果我输入 pos 文本,它就会变成 po [self text]。但如果有
Eclipse 没有调试我的 C++ 代码。它要求提供一个 gdb 版本。我修复了 gdb 的路径,但 .gdbinit 文件仍然丢失。我找不到它。调试过程现在刚刚终止。 eclipse 是否有一个内
抱歉我的无知,但我看到有很多关于 .gdbinit 文件的问题。我只是不明白这个文件给我带来了什么。似乎它用于现代 gdb 的一些 python 脚本,使 gdb 的输出更具可读性。 但是确切的区别是
有没有办法重新加载.gdbinit 文件。 假设您已经在 gdb 中工作,并且已经对 .gdbinit 进行了更改,并且希望在不干扰当前 gdb 环境的情况下重新加载新的 .gdbinit。 这可能吗
我正在尝试设置一组函数,让 gdb 跳过这些函数以防止通过以下命令介入: skip myfunction .但是,如果我将它们放在 ~/.gdbinit 而不是在终端 gdb 提示符中说,我会得到错误
我有一个包含 GDB 断点的文件 ~/.gdb_bps。我使用 save Breakpoints .gdb_bps 生成了此文件。我试图在 GDB 启动时通过将此行添加到 ~/.gdbinit 来获取
我是 python 的新手,我习惯使用 gdb。我想知道是否有一种方法可以为 pdb 提供一个类似于 .gdbinit 的初始化文件。主要原因是因为我想定义函数,这样我就不必输入 import os;
我正在使用 Inet,我对我的工作做了一些修改。我创建了一个新的地址类(我没有任何错误)。当我想在我的文件 .cc 中使用此类时我收到此错误: Warning: opp_run: Cannot ch
我遇到异常崩溃问题,我正在尝试编辑此文件以获取有关崩溃的更多信息。 .gdbinit 在哪里,我该如何编辑它? 最佳答案 您也可以将.gdbinit 放在您的调试文件夹中,这更适用于调试不同的应用程序
You can run gdb without printing the front material, which describes gdb's non-warranty, by specifyi
我在编程方面的知识和经验还很新鲜和基础,所以请多多包涵。 我希望能够通过 Eclipse 在我的 MacBook(操作系统 10.9.5 Mavericks)上使用 C++,我之前已经将其用于 Jav
在我的 ~/.gdbinit 中,我希望能够通过相对路径引用安装在我的主目录中的 GDB python pretty-print : python import sys # 1, works sys.
这是一个看似微不足道的问题,但我找不到一个简单的方法来完成它。 我的 .gdbinit 文件定义在与 gdb.exe 所在的同一目录中——即在我的编译器的 bin 目录中。但是,当我运行 gdb 时,
这里是放置在 ~/.gdbinit 中的断点列表,它们对调试内存问题非常有帮助: fb -[NSException raise] fb -[NSAssertionHandler handleFailu
使用原始 gdb (Debian 8.2.1-2) 调试 RefPerSys(GPLv3+,在 gitlab 上)提交 ec4ab756d302056cace0b在我的 Linux/x86-64/De
如何将命令“commands break#”放入 .gdbinit 中?我试过了但是失败了。谢谢 define macro1 b func1 commands p func1_
应该叫.gdbinit还是gdb.ini? 我想我会试试 this文件。 我正在使用使用 MinGw 的 Vectorcast 进行测试。我将具有两个名称(.gdbinit 和 gdb.ini)的文件
我正在尝试创建一个 ~/.gdbinit,其中包含一些用于各种 Qt 对象的 Qt pretty-print ,尤其是 QString。我想在没有 Qt Creator 的情况下使用常规 GDB 来执
我希望在使用 gdb 调试时设置源代码的路径。我选择使用 .gdbinit 文件来执行此操作。 基本上,它包含一个命令: directory="/path/to/src". 但是,我希望能够将该命令指
我是一名优秀的程序员,十分优秀!