8 查看栈信息
The call stack is divided up into contiguous pieces called stack frames, or frames for short; each frame is the data associated with one call to one function. The frame contains the arguments given to the function, the function’s local variables, and the address at which the function is executing. When your program is started, the stack has only one frame, that of the function main. This is called the initial frame or the outermost frame. Each time a function is called, a new frame is made. Each time a function returns, the frame for that function invocation is eliminated. If a function is recursive, there can be many frames for the same function. The frame for the function in which execution is actually occurring is called the innermost frame.
This is the most recently created of all the stack frames that still exist.
Inside your program, stack frames are identified by their addresses. A stack frame consists of many bytes, each of which has its own address; each kind of computer has a convention for choosing one byte whose address serves as the address of the frame. Usually
this address is kept in a register called the frame pointer register while execution is going on in that frame. gdb assigns numbers to all existing stack frames, starting with zero for the innermost frame, one for the frame that called it, and so on upward. These numbers do not really exist in your program;
they are assigned by gdb to give you a way of designating stack frames in gdb commands.
当程序被停住了,你需要做的第一件事就是查看程序是在哪里停住的。当你的程序调用了一个函数,函数的地址,函数参数,函数内的局部变量都会被压入“栈”(Stack)中。你可以用GDB命令来查看当前的栈中的信息。
下面是一些查看函数调用栈信息的GDB命令:
backtrace
bt
打印当前的函数调用栈的所有信息。如:
(gdb) bt
#0 func (n=250) at tst.c:6
#1 0x08048524 in
main (argc=1, argv=0xbffff674) at tst.c:30
#2 0x40040Arrayed in __libc_start_main () from /lib/libc.so.6
从上可以看出函数的调用栈信息:__libc_start_main
--> main() --> func()
backtrace n
bt n
n是一个正整数,表示只打印栈顶上n层的栈信息。
backtrace -n
bt -n
-n表一个负整数,表示只打印栈底下n层的栈信息。
如果你要查看某一层的信息,你需要在切换当前的栈,一般来说,程序停止时,最顶层的栈就是当前栈,如果你要查看栈下面层的详细信息,首先要做的是切换当前栈。
frame n
n是一个从0开始的整数,是栈中的层编号。比如:frame 0,表示栈顶,frame 1,表示栈的第二层。
frame addr
f addr
Select the frame at address addr. This is useful mainly if the chaining of
stack frames has been damaged by a bug, making it impossible for gdb to assign
numbers
properly to all frames. In addition, this can be useful when your program has
multiple stacks and switches between them.
up n
表示向栈的上面移动n层,可以不打n,表示向上移动一层。
down n
表示向栈的下面移动n层,可以不打n,表示向下移动一层。
上面的命令,都会打印出移动到的栈层的信息。如果你不想让其打出信息。你可以使用这三个命令:
select-frame 对应于 frame 命令。
up-silently n 对应于 up 命令。
down-silently n 对应于 down 命令。
查看当前栈层的信息,你可以用以下GDB命令:
frame 或 f
会打印出这些信息:栈的层编号,当前的函数名,函数参数值,函数所在文件及行号,函数执行到的语句。
info frame
info f
This command prints a verbose description of
the selected stack frame, including:
• the
address of the frame
• the
address of the next frame down (called by this frame)
• the
address of the next frame up (caller of this frame)
• the
language in which the source code corresponding to this frame is written
• the
address of the frame’s arguments
• the
address of the frame’s local variables
• the
program counter saved in it (the address of execution in the caller
frame)
•
which registers were saved in the frame
The
verbose description is useful when something has gone wrong that has made
the
stack format fail to fit the usual conventions.
这个命令会打印出更为详细的当前栈层的信息,只不过,大多数都是运行时的内内地址。比如:函数地址,调用函数的地址,被调用函数的地址,目前的函数是由什么样的程序语言写成的、函数参数地址及值、局部变量的地址等等。如:
(gdb) info f
Stack level 0, frame at 0xbffff5d4:
eip = 0x804845d in func (tst.c:6); saved eip 0x8048524
called by frame at 0xbffff60c
source language c.
Arglist at 0xbffff5d4, args: n=250
Locals at 0xbffff5d4, Previous frame’s sp is 0x0
Saved registers:
ebp at 0xbffff5d4, eip at 0xbffff5d8
info
frame addr
info f
addr
Print
a verbose description of the frame at address addr, without selecting that
frame.
The selected frame remains unchanged by this command. This requires the same
kind of address (more than one for some architectures) that you specify
in the
frame command.
info args
Print the arguments of the selected frame, each on a separate line.
info locals
打印出当前函数中所有局部变量及其值。
info catch
打印出当前的函数中的异常处理信息。