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

Viewed 10557

I am having a slight problem with some structs in a kernel module I'm building, so I thought it would be nice if there was an easy way to print out structs and their values - and below is a small userland example of what I mean.

Say we have the simple C example as below (given in form of a bash commands):

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 

 

If we run this example, the program will compile, and gdb will run it, and automatically stop at the breakpoint. Here we can do the following:

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

 

As shown, in gdb we can printout (dump?) the value of the struct pointer johndoe as {age = 6, height = 0} ... I would like to do the same, but directly from a C program; say as in the following example:

#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);
}

 

which would result with an output like:

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

 

So my question is - does a function like that imaginary printout_struct exist - or is there another approach to make a printout like this possible?

Thanks in advance for any help,
Cheers!

6 Answers

Here is more efficient solution for user mode, not kernel, which prepares gdb script. Then an application is executed via gdb with the script. The script contains breakpoints with commands. In a source code need to mark breakpoints with empty define:

#define gdb_print(v)

gdb_print(huge_struct);


gdb-print-prepare()
{
    # usage:
    # gdb-print-prepare $src > app.gdb
    # gdb --batch --quiet --command=app.gdb app
    cat  <<-EOF
    set auto-load safe-path /
    EOF
    grep --with-filename --line-number --recursive '^\s\+gdb_print(.*);' $1 | \
    while IFS=$'\t ;()' read line func var rest; do
        cat  <<-EOF
        break ${line%:}
        commands
        silent
        where 1
        echo \\n$var\\n
        print $var
        cont
        end
        EOF
    done
    cat  <<-EOF
    run
    bt
    echo ---\\n
    EOF
}

Reference: https://gitlab.com/makelinux/lib/blob/master/snippets/gdb-print-prepare.md

Related