user1627854
user1627854

Reputation: 11

Can I list the local variables in a stack by using some system functions in C language

The C function backtrace just returns a series of functions calls for the programn, but i want to list all the locals variables in my programn, just like the info locals in gdb.Any idea if this can be done? Thanks

Upvotes: 1

Views: 107

Answers (3)

John Bode
John Bode

Reputation: 123488

First, note that backtrace is not a standard C library function, but a GNU-specific extension.

In general, it's difficult to impossible retrieve local variable information from compiled code, especially if it was compiled without debugging or with optimization enabled. If debugging isn't turned on, variable names and types are generally not preserved in the resulting machine code.

For example, take the following ridiculously simple code:

#include <stdio.h>
#include <math.h>

int main(void)
{
  int x = 1, y = 2, z;
  z = 2 * y - x;
  printf("x = %d, y = %d, z = %d\n", x, y, z);
  return 0;
}

Here's the resulting machine code, no debugging or optimization:

        .file   "varinfo.c"
        .version        "01.01"
gcc2_compiled.:
                .section        .rodata
.LC0:
        .string "x = %d, y = %d, z = %d\n"
.text
        .align 4
.globl main
        .type    main,@function
main:
        pushl   %ebp
        movl    %esp, %ebp
        subl    $24, %esp
        movl    $1, -4(%ebp)
        movl    $2, -8(%ebp)
        movl    -8(%ebp), %eax
        movl    %eax, %eax
        sall    $1, %eax
        subl    -4(%ebp), %eax
        movl    %eax, -12(%ebp)
        pushl   -12(%ebp)
        pushl   -8(%ebp)
        pushl   -4(%ebp)
        pushl   $.LC0
        call    printf
        addl    $16, %esp
        movl    $0, %eax
        leave
        ret
.Lfe1:
        .size    main,.Lfe1-main
        .ident  "GCC: (GNU) 2.96 20000731 (Red Hat Linux 7.2 2.96-112.7.2)"

x, y, and z are referred to through -4(%ebp), -8(%ebp), and -12(%ebp) respectively. There's nothing to indicate that they're integers other than the instructions used to perform the arithmetic.

It's even better with optimization (-O1) turned on:

        .file   "varinfo.c"
        .version        "01.01"
gcc2_compiled.:
        .section        .rodata.str1.1,"ams",@progbits,1
.LC0:
        .string "x = %d, y = %d, z = %d\n"
.text
        .align 4
.globl main
        .type    main,@function
main:
        pushl   %ebp
        movl    %esp, %ebp
        subl    $8, %esp
        pushl   $3
        pushl   $2
        pushl   $1
        pushl   $.LC0
        call    printf
        movl    $0, %eax
        leave
        ret
.Lfe1:
        .size    main,.Lfe1-main
        .ident  "GCC: (GNU) 2.96 20000731 (Red Hat Linux 7.2 2.96-112.7.2)"

In this case, the compiler was able to do some static analysis and compute the value z at compile time; there's no need to set aside any memory for any of the variables at all, because the compiler already knows what those values have to be.

Upvotes: 0

jxh
jxh

Reputation: 70422

If this is just for occasional debugging, then you can invoke the debugger. However, since the debugger itself will freeze your program, you need an intermediary to capture the output. You can, for example, use system, and redirect the output to a file, then read the file afterwards. In the example below, the file gdbcmds.txt contains the line info locals.

char buf[512];
FILE *gdb;
snprintf(buf, sizeof(buf), "gdb -batch -x gdbcmds.txt -p %d > gdbout.txt",
         (int)getpid());
system(buf);
gdb = fopen("gdbout.txt", "r");
while (fgets(buf, sizeof(buf), gdb) != 0) {
    printf("%s", buf);
}
fclose(gdb);

Upvotes: 0

Kerrek SB
Kerrek SB

Reputation: 477130

Generally, no. You should move away from thinking about a "stack" as some sort of god given factum. A call stack is merely a common implementation technique for C. It has no intrinsic meaning or required semantics. Automatic variables ("local variables", as you say) have to behave in a certain way, and sometimes that means that they are written onto the call stack. However, it is entirely conceivable that local variables are never realized in memory at all -- they may instead only ever be stored in a processor register, or eliminated entirely if an equivalent program can be formulated without them.

So, no, there is no language-intrinsic mechanism for enumerating local variables. As you say, the debugger can do so to some extent (depending on debug symbols being present and subject to optimizations); perhaps you can find a library that can process debug symbols from within a running program.

Upvotes: 3

Related Questions