如何使gdb以十六进制而不是八进制打印字符串中不可打印的字符,同时保留ascii格式的ascii字符?

如何使gdb以十六进制而不是八进制打印字符串中不可打印的字符,同时保留ascii格式的ascii字符?,c,string,debugging,assembly,gdb,C,String,Debugging,Assembly,Gdb,假设我有一个bufferbuf,它的c字符串表示是 char* buf = "Hello World \x1c" 当我使用命令pbuf在gdb中打印这个buf时,我得到以下结果 $1 = "Hello World \034" 是否有打印命令或gdb设置将打印以下内容? $1 = "Hello World \x1c" 我尝试过各种格式参数,如/c和/x,但它们都没有达到我想要的效果。我也玩过printf,但没能达到预期的效果 更新:我正在使用“GNUGDB(gdb)7.0.1-debia

假设我有一个buffer
buf
,它的c字符串表示是

 char* buf = "Hello World \x1c"
当我使用命令
pbuf
在gdb中打印这个buf时,我得到以下结果

 $1 = "Hello World \034"
是否有打印命令或gdb设置将打印以下内容?

$1 = "Hello World \x1c"
我尝试过各种格式参数,如
/c
/x
,但它们都没有达到我想要的效果。我也玩过printf,但没能达到预期的效果

更新:我正在使用“GNUGDB(gdb)7.0.1-debian”

更新: 我也和x打过球

如果我执行
x/c
操作,它会打印不可打印字符的八进制和十进制,然后打印ascii和十进制的可打印字符

如果我执行
x/s
,它的输出与p命令完全相同

如果我执行
x/x
,它只输出十六进制,但是我们会丢失可打印部分的ascii字符


更新:除非不完整,否则这表明我想要的东西不可用,但有人能确认吗?

您可以使用
x
命令转储您的
char
-指针指向:

(gdb) x/32xb buf
显示前32个字节


详细信息。

在缺乏现有解决方案的情况下,我创建了一个为混合了可打印ascii和不可打印字符的字符串打印ascii和十六进制的解决方案。资料来源转载如下

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()
要使用它,只需将
源代码AsciiPrintCommand.py
放入gdb中,然后运行以下命令。为了方便起见,可以将上述源代码命令放入它们的
$HOME/.gdbinit

ascii-print buf
"Hello World \x1c"

OP答案的一个小变化,对于8位数组的用例,它不一定在
\0
的第一次出现时终止,并且尝试也尊重
打印元素
打印重复
GDB的参数:

from\uuuuu future\uuuuu导入打印功能
def print_extended_ascii_字符(字符码):
如果charCode==ord(“”):返回r'\“'
如果charCode==ord('\\'):返回r'\\'
如果32限制或未打印[0]为无:
打印(“”)
elif repeats==“无限”或未打印[1]<重复:
打印(未打印[0]*未打印[1],结束=“”)
打印(“”)
其他:
打印(“,”)
打印(“%s”)(未打印[0],未打印[1]-1))
PrettyPrintString()
如前所述,将上述内容放在某个文件中(例如
~/.gdb AsciiPrint.py
),然后运行
source~/.gdb AsciiPrint.py
,或者将该语句放在
.gdbinit
文件中。 结果/比较:

(gdb) p tokmem[3]
$1 = "\000\030\000-1\320\a\200\031:\200\032[\200\024]\200\033\200\023;\200\034:\200\032[\200\023]\200\033\200\024;\320\r\200$:\200\030;\320\020\200 k\030\060\200!255\200\"\200\r\200\060(k:3,': \"');l\030k;\200+(\250\061)\200,\200\r\200\060(\200\034[\200\062],\200\034[\200\062]);\200+k<\f100\200,l\030k+\f100\200.\200+k<\f200\200,l\030k-\f100\200.\200\r\200*(k\200\063\061\066);\200\060(\200\034[l]);\200*(k\200\064\061\066);\200\020(\200$);\200\017;\200$\030\200$+2;\200\017;\200+l=\200\065\200,\200\060(\200\034[l],\200\034[l])\200.\200\060(\200\034[l]);\200\020(\200$);\200&('\"');\200\017", '\000' <repeats 65285 times>
(gdb) ascii-print tokmem[3]
"\x00\x18\x00-1\xd0\x07\x80\x19:\x80\x1a[\x80\x14]\x80\x1b\x80\x13;\x80\x1c:\x80\x1a[\x80\x13]\x80\x1b\x80\x14;\xd0\x0d\x80$:\x80\x18;\xd0\x10\x80 k\x180\x80!255\x80\"\x80\x0d\x800(k:3,': \"');l\x18k;\x80+(\xa81)\x80,\x80\x0d\x800(\x80\x1c[\x802],\x80\x1c[\x802]);\x80+k<\x0c100\x80,l\x18k+\x0c100\x80.\x80+k<\x0c200\x80,l\x18k-\x0c100\x80.\x80\x0d\x80*(k\x80316);\x800(\x80\x1c[l]);\x80*(k\x80416);\x80\x10(\x80$);\x80\x0f;\x80$\x18\x80$+2;\x80\x0f;\x80+l=\x805\x80,\x800(\x80\x1c[l],\x80\x1c[l])\x80.\x800(\x80\x1c[l]);\x80\x10(\x80$);\x80&('\"');\x80\x0f",
'\x00' <repeats 65285 times>
(gdb)p tokmem[3]

$1=“\000\030\000-1\320\a\200\031:\200\032[\200\024]\200\033\200\023\200\034:\200\032[\200\023]\200\033\200\024;\320\r\200$:\200\030\320\020\200K\030\060\200!255\200\“\200\r\200\060(k:3,,:\”);l\030k\200+(\250\061)\200\200\r\200\060(\200\034[\200\062],\200\034[\200\062])\200+k对于在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行-然后所有转义序列将以十六进制打印。

根据您在字符串中显示非ascii字符的原因,稍微不同的方法可能是使用不同的编码打印字符串

在我的例子中,我希望看到十六进制值,以确保字符串是在UTF-8环境中使用ISO8859-1编码的。尽管如此,它并不打算或可用于此目的

在探索OP创建的gdb命令时,我发现了一个将gdb值打印为字符串(如果是字符串)的命令。您可以为它提供一个编码选项,以便以下Python代码向GDB添加一个
isostring
命令:

from\uuuuu future\uuuuu导入打印功能
类PrettyPrintString(gdb.Command):
“”“将8位字节数组打印为ISO8859-1的命令”“”
定义初始化(自):
super(PrettyPrintString,self)。\uuuu init\uuuu(name=“isostring”,
command\u class=gdb.command\u数据,
completer_class=gdb.COMPLETE_表达式,前缀=True)
def调用(self、arg、from_tty):
如果不是arg.strip():
打印(“您希望我打印什么?”)
返回
value=gdb.parse_和_eval(arg)
打印(“”+value.string(“iso8859-1”)+“”)
PrettyPrintString()

我正在进行一些asm调试,并试图通过使十六进制和ascii在字符串中并排时易于独立读取来最大限度地提高可读性。看起来八进制在当时非常流行。我问(多亏了一位看到这个问题的人,Emacs增加了一个特性),现在在阅读TeX的源代码和查看gdb输出时又遇到了八进制。:-)感谢您的提问和回答。我尝试了您的解决方案,并将其保存到~/.gdb-ascii-print.py文件中。源代码~/.gdb-ascii-print0.py回溯(上次调用):文件“~/.gdb-ascii-print0.py”,第31行,在文件“~/.gdb-ascii-print0.py”的第11行,在init AttributeError中:“模块”对象没有属性“完整表达式”
/* If the value fits in 3 octal digits, print it that
                     way.  Otherwise, print it as a hex escape.  */