Linux 打印堆栈指针的值
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/20059673/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Print out value of stack pointer
提问by Juicy
How can I print out the current value at the stack pointer in C in Linux (Debian and Ubuntu)?
如何在 Linux(Debian 和 Ubuntu)中用 C 语言打印堆栈指针处的当前值?
I tried google but found no results.
我试过谷歌,但没有找到任何结果。
采纳答案by JaredPar
One trick, which is not portable or really even guaranteed to work, is to simple print out the address of a local as a pointer.
一种不可移植甚至不能保证工作的技巧是简单地将本地地址作为指针打印出来。
void print_stack_pointer() {
void* p = NULL;
printf("%p", (void*)&p);
}
This will essentially print out the address of p
which is a good approximation of the current stack pointer
这基本上将打印出其地址p
是当前堆栈指针的一个很好的近似值
回答by duedl0r
There is no portable way to do that.
没有便携式方法可以做到这一点。
In GNU C, this may work for target ISAs that have a register named SP, including x86 where gcc recognizes "SP" as short for ESP or RSP.
在 GNU C 中,这可能适用于具有名为 SP 的寄存器的目标 ISA,包括 x86,其中 gcc 将“SP”识别为 ESP 或 RSP 的缩写。
// broken with clang, but usually works with GCC
register void *sp asm ("sp");
printf("%p", sp);
This usage of local register variablesis now deprecated by GCC:
GCC 现在不赞成使用本地寄存器变量:
The only supported use for this feature is to specify registers for input and output operands when calling Extended asm
Defining a register variable does not reserve the register. Other than when invoking the Extended asm, the contents of the specified register are not guaranteed. For this reason, the following uses are explicitly not supported. If they appear to work, it is only happenstance, and may stop working as intended due to (seemingly) unrelated changes in surrounding code, or even minor changes in the optimization of a future version of gcc. ...
此功能唯一支持的用途是在调用扩展 asm时为输入和输出操作数指定寄存器
定义寄存器变量不会保留寄存器。除了调用扩展汇编时,不保证指定寄存器的内容。因此,明确不支持以下用途。如果它们看起来有效,那只是偶然,并且可能会由于周围代码中(看似)无关的更改,甚至是 gcc 未来版本的优化中的微小更改而停止按预期工作。...
It's also broken in practice with clang where sp
is treated like any other uninitialized variable.
它在实践中也被 clang 破坏,在那里sp
被视为任何其他未初始化的变量。
回答by Basile Starynkevitch
In addition to duedl0r's answerwith specifically GCCyou could use __builtin_frame_address(0)
which is GCC specific (but not x86specific).
除了duedl0r的回答与具体GCC,你可以使用__builtin_frame_address(0)
它是GCC特定的(但不是x86的具体)。
This should also work on Clang(but there are some bugsabout it).
Taking the address of a local (as JaredPar answered) is also a solution.
获取本地地址(正如JaredPar 回答的那样)也是一种解决方案。
Notice that AFAIK the C standard does not require any call stack in theory.
请注意,AFAIK C 标准理论上不需要任何调用堆栈。
Remember Appel's paper: garbage collection can be faster than stack allocation; A very weird C implementation could use such a technique! But AFAIK it has never been used for C.
记住 Appel 的论文:垃圾收集可以比堆栈分配更快;一个非常奇怪的 C 实现可以使用这样的技术!但 AFAIK 它从未用于 C。
One could dream of a other techniques. And you could have split stacks(at least on recent GCC), in which case the very notion of stack pointer has much less sense (because then the stack is not contiguous, and could be made of many segments of a few call frames each).
人们可以梦想其他技术。并且您可以拆分堆栈(至少在最近的 GCC 上),在这种情况下,堆栈指针的概念意义要小得多(因为堆栈不是连续的,并且可以由许多段组成,每个段都有几个调用帧) .
回答by Paschalis
On Linux
you can use the proc
pseudo-filesystem to print the stack pointer.
在Linux
你可以使用proc
伪文件系统打印的堆栈指针。
Have a look here, at the /proc/your-pid/stat pseudo-file, at the fields 28
, 29
.
看看这里,以在/ proc /你-PID / STAT伪文件,在田野28
,29
。
startstack %luThe address of the start (i.e., bottom) of the stack.
kstkesp %luThe current value of ESP (stack pointer), as found in the kernel stack page for the process.
startstack %lu堆栈开始(即底部)的地址。
kstkesp %luESP(堆栈指针)的当前值,在进程的内核堆栈页面中找到。
You just have to parse these two values!
你只需要解析这两个值!
回答by baz
u can also use an extended assembler instruction for example
例如,您还可以使用扩展汇编指令
#include <stdint.h>
uint64_t getsp( void )
{
uint64_t sp;
asm( "mov %%rsp, %0" : "=rm" ( sp ));
return sp;
}
for 32 bit system 64 has to be replaced with 32 and rsp with esp
对于 32 位系统,必须用 32 替换 64,用 esp 替换 rsp
回答by Garmekain
You have that info in the file /proc/<your-process-id>/maps
, in the same line as the string [stack]
appears(so it is independent of the compiler or machine). The only downside of this approach is that for that file to be read it is needed to be root.
您在文件中拥有该信息,与/proc/<your-process-id>/maps
字符串[stack]
出现在同一行(因此它独立于编译器或机器)。这种方法的唯一缺点是要读取的文件需要是 root 用户。
回答by Victor Choy
Try lldb or gdb. For example we can set backtrace format in lldb.
试试 lldb 或 gdb。例如我们可以在 lldb 中设置回溯格式。
settings set frame-format "frame #${frame.index}: ${ansi.fg.yellow}${frame.pc}: {pc:${frame.pc},fp:${frame.fp},sp:${frame.sp}} ${ansi.normal}{ ${module.file.basename}{\`${function.name-with-args}{${frame.no-debug}${function.pc-offset}}}}{ at ${ansi.fg.cyan}${line.file.basename}${ansi.normal}:${ansi.fg.yellow}${line.number}${ansi.normal}{:${ansi.fg.yellow}${line.column}${ansi.normal}}}{${function.is-optimized} [opt]}{${frame.is-artificial} [artificial]}\n"
So we can print the bp , sp in debug such as
所以我们可以在调试中打印 bp , sp ,例如
frame #10: 0x208895c4: pc:0x208895c4,fp:0x01f7d458,sp:0x01f7d414 UIKit`-[UIApplication _handleDelegateCallbacksWithOptions:isSuspended:restoreState:] + 376
Look more at https://lldb.llvm.org/use/formatting.html