- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有汇编代码,由 frameCount 调用,需要返回 frameCount,但不确定如何检索(然后导航)前一帧的指针引用。
getFP.s
.globl getFP
getFP:
movq %rbp, %rax
ret
frameCount.c
int frameCount() {
int count = 0;
uint64_t fp = getFP();
uint64_t *sp = &fp;
// how do I get the pointer/offset to pointer to the previous stack frame from here?
return count;
}
我已更新 frameCount 函数以包含一个遍历堆栈帧链表的循环,但在调用 frameCount 时出现段错误。
main.c
#include <stdio.h>
#include <inttypes.h>
#include "framecount.c"
int main() {
printf("Number of Frames: %d\n", frameCount());
return(0);
}
frameCount.c
#include <stdio.h>
#include <inttypes.h>
uint64_t* getFP();
int frameCount() {
uint64_t* fp = getFP();
uint64_t registerValue1 = *fp;
while (registerValue1 != 0) {
printf("current register value %" PRIx64 "\n", registerValue1);
printf("next register value %" PRIx64 "\n", *(volatile uint64_t *)registerValue1);
count++;
registerValue1 = *(volatile uint64_t *)registerValue1;
}
printf("count=%d\n", count);
return count;
}
输出
current register value 7ffca7c147b0
next register value 401230
current register value 401230
next register value 8d4c5741fa1e0ff3
current register value 8d4c5741fa1e0ff3
Segmentation fault (core dumped)
但是,当我执行以下操作时,我没有遇到段错误,但计数似乎不正确:(更新:删除虚假示例)
即使使用选项 -O0
或 -fno-omit-frame-pointer
运行时仍然出现段错误,这是初始第一次更新的程序集输出:
.file "lab7.c"
.text
.section .rodata
.LC0:
.string "%d"
.text
.globl frameCount
.type frameCount, @function
frameCount:
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
subq $32, %rsp
movl $0, -4(%rbp)
movl $0, %eax
call getFP
movq %rax, -24(%rbp)
movq -24(%rbp), %rax
movq (%rax), %rax
movq %rax, -16(%rbp)
jmp .L2
.L3:
addl $1, -4(%rbp)
movl -4(%rbp), %eax
movl %eax, %esi
movl $.LC0, %edi
movl $0, %eax
call printf
movq -16(%rbp), %rax
movq (%rax), %rax
movq %rax, -16(%rbp)
.L2:
cmpq $0, -16(%rbp)
jne .L3
movl -4(%rbp), %eax
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size frameCount, .-frameCount
.section .rodata
.LC1:
.string "Number of Frames: %d\n"
.text
.globl main
.type main, @function
main:
.LFB1:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
movl $0, %eax
call frameCount
movl %eax, %esi
movl $.LC1, %edi
movl $0, %eax
call printf
movl $0, %eax
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE1:
.size main, .-main
.ident "GCC: (GNU) 10.2.1 20200723 (Red Hat 10.2.1-1)"
.section .note.GNU-stack,"",@progbits
最佳答案
一般来说,这种技术是行不通的。只有在编译器实际使用它们的情况下,这样的遍历堆栈帧才是可能的。在 Linux 和类似操作系统下的 x86-64 上,这不是 ABI 所要求的,并且在启用优化时不是大多数编译器的默认设置,但在 GCC 和 clang 上,您可以使用 -fno-omit-frame 请求它-指针
。但是,如果调用链中的某些函数在调用下一个函数时将 %rbp
用于其他用途,则存储的 %rbp
将不会指向前一个,并且您的程序可能会崩溃。有另一种方法可以使用存储在内存中其他位置的展开信息来遍历堆栈,但它很复杂,所以人们经常使用像 libbacktrace
这样的库。而是。
但是,当使用堆栈帧时:您可以查看 how a compiler sets them up :
pushq %rbp
movq %rsp, %rbp
由于 x86 push
指令将 %rsp
递减,然后将推送的值存储在 %rsp
指向的新地址,因此 >movq %rsp, %rbp
留下 %rbp
包含存储前一个 %rbp
的地址。堆栈帧顶部的 %rbp
值为 0,因此您可以简单地执行类似
for (uint64_t *fp = getFP(); fp; fp = (uint64_t *)*fp) count++;
关于c - 如何计算我的 frameCount 函数中的堆栈帧数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65028444/
我有汇编代码,由 frameCount 调用,需要返回 frameCount,但不确定如何检索(然后导航)前一帧的指针引用。 getFP.s .globl getFP getFP: movq
我试图让带圆圈的对象随着时间的推移出现——每个对象都是独立的——并在 30 帧后将它们的位置更改为随机选择的新对象。现在——我只能让它们在 30 帧后改变它们的位置,但同时全部在一起……我花了一段时间
我是一名优秀的程序员,十分优秀!