gpt4 book ai didi

c - Linux C : Easy & 'pretty' dump/printout of structs (like in gdb) - from source code?

转载 作者:IT王子 更新时间:2023-10-28 23:53:13 26 4
gpt4 key购买 nike

我正在构建的内核模块中的一些结构存在一个小问题,所以我认为如果有一种简单的方法来打印结构及其值会很好——下面是一个小的用户态示例我的意思。

假设我们有如下简单的 C 示例(以 bash 命令的形式给出):

FN=mtest

cat > $FN.c <<EOF
#include <stdio.h> //printf
#include <stdlib.h> //calloc

struct person
{
int age;
int height;
};

static struct person *johndoe;

main ()
{

johndoe = (struct person *)calloc(1, sizeof(struct person));
johndoe->age = 6;

asm("int3"); //breakpoint for gdb

printf("Hello World - age: %d\n", johndoe->age);

free(johndoe);
}
EOF

gcc -g -O0 $FN.c -o $FN

# just a run command for gdb
cat > ./gdbcmds <<EOF
run
EOF

gdb --command=./gdbcmds ./$FN

如果我们运行这个例子,程序会编译,gdb 会运行它,并在断点处自动停止。在这里我们可以做以下事情:

Program received signal SIGTRAP, Trace/breakpoint trap.
main () at mtest.c:20
20 printf("Hello World - age: %d\n", johndoe->age);
(gdb) p johndoe
$1 = (struct person *) 0x804b008
(gdb) p (struct person)*0x804b008
$2 = {age = 6, height = 0}
(gdb) c
Continuing.
Hello World - age: 6

Program exited with code 0300.
(gdb) q

如图所示,在 gdb 中我们可以将结构指针 johndoe 的值打印(转储?)为 {age = 6, height = 0} ... I想做同样的事情,但直接来自 C 程序;如以下示例所示:

#include <stdio.h> //printf
#include <stdlib.h> //calloc
#include <whatever.h> //for imaginary printout_struct

struct person
{
int age;
int height;
};

static struct person *johndoe;
static char report[255];

main ()
{

johndoe = (struct person *)calloc(1, sizeof(struct person));
johndoe->age = 6;

printout_struct(johndoe, report); //imaginary command

printf("Hello World - age: %d\nreport: %s", johndoe->age, report);

free(johndoe);
}

这将产生如下输出:

Hello World - age: 6
$2 = {age = 6, height = 0}

所以我的问题是 - 是否存在像虚构的 printout_struct 这样的函数 - 或者是否有另一种方法可以实现这样的打印输出?

在此先感谢您的帮助,
干杯!

最佳答案

只是想说 - 感谢您提供的所有出色且快速的答案,帮助我理解了问题(为什么 C 中没有这样的“ native ”函数)!

(很抱歉回答我自己的问题 - 这样做是为了不混淆原始帖子,并且能够格式化代码)

在进一步寻找的过程中,我设法找到了:

这说明了使用进程本身的 pid 调用 gdb 的技巧,因此我修改了在那里找到的 dumpstack 函数,以获得以下代码:

FN=mtest

cat > $FN.c <<EOF
#include <stdio.h> //printf
#include <stdlib.h> //calloc, system

extern const char *__progname;

struct person
{
int age;
int height;
};

static struct person *johndoe;
static char report[255];

static void printout_struct(void* invar, char* structname){
/* dumpstack(void) Got this routine from http://www.whitefang.com/unix/faq_toc.html
** Section 6.5. Modified to redirect to file to prevent clutter
*/
/* This needs to be changed... */
char dbx[160];

sprintf(dbx, "echo 'p (struct %s)*%p\n' > gdbcmds", structname, invar );
system(dbx);

sprintf(dbx, "echo 'where\ndetach' | gdb -batch --command=gdbcmds %s %d > struct.dump", __progname, getpid() );
system(dbx);

sprintf(dbx, "cat struct.dump");
system(dbx);

return;
}

main ()
{

johndoe = (struct person *)calloc(1, sizeof(struct person));

johndoe->age = 6;
printout_struct(johndoe, "person");

johndoe->age = 8;
printout_struct(johndoe, "person");

printf("Hello World - age: %d\n:", johndoe->age);

free(johndoe);
}


EOF

gcc -g -O0 $FN.c -o $FN

./$FN

基本上最终显示了我想要的内容:

0x00740422 in __kernel_vsyscall ()
$1 = {age = 6, height = 0}
0x00740422 in __kernel_vsyscall ()
$1 = {age = 8, height = 0}
Hello World - age: 8

不过,我不确定它是否适用于内核模块......

再次感谢您的帮助,
干杯!

编辑:我认为它不适用于内核模块的原因是,在这种情况下,我们有一个带有进程 ID 的用户态程序;我们只需从这个程序中调用 gdb,同时向它指示我们的 PID - 这样 gdb 就可以“附加”到我们的进程;然后,由于还指示 gdb 加载带有调试符号的可执行文件(因此它将“知道”结构是什么),并指示给定结构变量所在的地址, gdb 然后可以打印出结构。

对于内核模块——首先,我不认为它们是具有唯一 PID 的“进程”,因此 gdb 将没有任何附加对象!事实上,有一个内核调试器,kgdb它实际上可以闯入正在运行的内核并单步执行模块源代码;但是,您需要通过串行连接连接第二台机器 - 或者虚拟机,请参阅 Linux Hacks: Setting up kgdb using kvm/qemu .

因此,无论如何,gdb 似乎无法检查当前正在运行的主机内核的内存 gdb 正在运行 - 但我会尝试进行实验,如果实验结果并非如此,我一定会发布 :)

关于c - Linux C : Easy & 'pretty' dump/printout of structs (like in gdb) - from source code?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3311182/

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