假设我有一个缓冲区buf
,其c字符串表示为
char* buf = "Hello World \x1c"
当我使用命令p buf
在gdb中打印此buf时,我得到以下内容
$1 = "Hello World \034"
是否有打印命令或gdb设置会打印以下内容?
$1 = "Hello World \x1c"
我尝试了各种格式参数,例如/c
和/x
,但它们都没有达到我想要的效果。我也玩过printf但是无法达到预期的效果。
更新:我正在使用“GNU gdb(GDB)7.0.1-debian”。
更新: 我也玩过x。
如果我x/c
,它会为非打印字符打印八进制和十进制,然后打印带有ascii和decimal的可打印字符。
如果我x/s
,它输出与p命令完全相同。
如果我x/x
它只输出十六进制但我们丢失了可打印部分的ascii字符。
更新:此reference,除非不完整,否则表示我想要的内容不可用,但有人可以确认吗?
答案 0 :(得分:6)
在没有现有解决方案的情况下,我创建了this gdb command,它为具有混合可打印ascii和不可打印字符的字符串输出ascii和hex。来源转载如下。
from __future__ import print_function
import gdb
import string
class PrettyPrintString (gdb.Command):
"Command to print strings with a mix of ascii and hex."
def __init__(self):
super (PrettyPrintString, self).__init__("ascii-print",
gdb.COMMAND_DATA,
gdb.COMPLETE_EXPRESSION, True)
gdb.execute("alias -a pp = ascii-print", True)
def invoke(self, arg, from_tty):
arg = arg.strip()
if arg == "":
print("Argument required (starting display address).")
return
startingAddress = gdb.parse_and_eval(arg)
p = 0
print('"', end='')
while startingAddress[p] != ord("\0"):
charCode = int(startingAddress[p].cast(gdb.lookup_type("char")))
if chr(charCode) in string.printable:
print("%c" % chr(charCode), end='')
else:
print("\\x%x" % charCode, end='')
p += 1
print('"')
PrettyPrintString()
要使用它,可以简单地放置source AsciiPrintCommand.py
,然后在gdb中运行以下命令。为方便起见,可以将上述源命令放入$HOME/.gdbinit
。
ascii-print buf
"Hello World \x1c"
答案 1 :(得分:4)
您可以使用x
命令转储字符串引用指向的内存:
(gdb) x/32xb buf
显示前32个字节。
见
(gdb) help x
了解详情。
答案 2 :(得分:4)
对于在GDB中与八进制转义序列有共同点的其他人,很容易解决(如果您准备自己构建GDB):在gdb / valprint.c中,找到注释:
/* If the value fits in 3 octal digits, print it that
way. Otherwise, print it as a hex escape. */
并注释掉以下4行-所有转义序列都将以十六进制打印。
答案 3 :(得分:1)
OP答案的一个小变化,适用于8位数组的用例,这些数组不一定在第一次出现[i][j]
时就终止,并且还尝试遵守\0
和GDB的print elements
参数:
print repeats
像以前一样,将以上内容放入某个文件(例如from __future__ import print_function
def print_extended_ascii_char(charCode):
if charCode == ord('"'): return r'\"'
if charCode == ord('\\'): return r'\\'
if 32 <= charCode <= 126: return "%c" % charCode
return r"\x%02x" % charCode
def get_gdb_value(command, output_re):
try:
import re
s = gdb.execute(command, to_string=True)
m = re.match(output_re, s)
value = m.group(1)
if value != 'unlimited':
value = int(value)
return value
except Exception as e:
print("Sorry, ran into an error running '%s' and getting the value." % command)
raise e
class PrettyPrintString(gdb.Command):
"""Command to print an array of 8-bit bytes, using ASCII when possible and hex otherwise.
https://stackoverflow.com/a/54469844/4958"""
def __init__(self):
super (PrettyPrintString, self).__init__(name="ascii-print",
command_class=gdb.COMMAND_DATA,
completer_class=gdb.COMPLETE_EXPRESSION, prefix=True)
def invoke(self, arg, from_tty):
if not arg.strip():
print("What do you want me to print?")
return
limit = get_gdb_value('show print elements', 'Limit on string chars or array elements to print is (.*).\n')
repeats = get_gdb_value('show print repeats', 'Threshold for repeated print elements is (.*).\n')
start = gdb.parse_and_eval(arg)
p = 0
print('"', end='')
i = 0
unprinted = (None, 0)
while i < start.type.sizeof:
i += 1
charCode = int(start[p])
toPrint = print_extended_ascii_char(charCode)
if toPrint == unprinted[0]:
unprinted = (toPrint, unprinted[1] + 1)
else:
if unprinted[0] is not None:
print(unprinted[0] * min(unprinted[1], limit - (i - unprinted[1])), end='')
if i > limit:
print('...', end='')
break
unprinted = (toPrint, 1)
p += 1
if i - unprinted[1] > limit or unprinted[0] is None:
print('"')
elif repeats == 'unlimited' or unprinted[1] < repeats:
print(unprinted[0] * unprinted[1], end='')
print('"')
else:
print('",')
print("'%s' <repeats %d times>" % (unprinted[0], unprinted[1] - 1))
PrettyPrintString()
)中,然后运行~/.gdb-AsciiPrint.py
或将该语句放入source ~/.gdb-AsciiPrint.py
文件中。
结果/比较:
.gdbinit
这有点hacky,因此希望该功能将被添加到GDB本身。
(在旁边:我问a similar question for Emacs,看到这个问题的人中的一个人提出了a patch to Emacs。如今,八进制似乎比以前不那么流行了;例如JavaScript的字符串文字有deprecated octal个转义序列。)
答案 4 :(得分:1)
根据您在字符串中显示非 ascii 字符的原因,一种稍微不同的方法可能是使用不同的编码打印字符串。
就我而言,我想查看十六进制值以确保字符串是在 UTF-8 环境中使用 ISO8859-1 编码的。尽管 GDB has encoding,但它并非旨在或可用于此目的。
在探索由 OP 和 ShreevatsaR 创建的 gdb 命令时,我发现了 Value.string()
function 将 GDB 值打印为字符串(如果它是字符串)。您可以给它一个编码选项,以便以下 Python 代码向 GDB 添加一个 isostring
命令:
from __future__ import print_function
class PrettyPrintString(gdb.Command):
"""Command to print an array of 8-bit bytes as ISO8859-1"""
def __init__(self):
super (PrettyPrintString, self).__init__(name="isostring",
command_class=gdb.COMMAND_DATA,
completer_class=gdb.COMPLETE_EXPRESSION, prefix=True)
def invoke(self, arg, from_tty):
if not arg.strip():
print("What do you want me to print?")
return
value = gdb.parse_and_eval(arg)
print('"' + value.string("iso8859-1")+ '"')
PrettyPrintString()