.text .data 和 main 的分段错误(主要在 .data 部分)

Posted

技术标签:

【中文标题】.text .data 和 main 的分段错误(主要在 .data 部分)【英文标题】:segmentation fault with .text .data and main (main in .data section) 【发布时间】:2016-03-24 20:46:16 【问题描述】:

我只是想将myarray[0] 的值加载到eax

        .text
        .data

        # define an array of 3 words
array_words:     .word 1, 2, 3

        .globl main

main:
        # assign array_words[0] to eax
        mov $0, %edi
        lea array_words(,%edi,4), %eax

但是当我运行它时,我不断收到段错误。 有人可以指出我在这里做错了什么吗?

【问题讨论】:

lea 是您代码中的最后一条指令吗?意思是,上面的sn-p是你所有的吗? 编者按:原标题为“将数组的值分配给eax时出现分段错误”。我重新命名以使其成为一个更好的重复目标(链接标题指出问题),以解决其他有这个简单错误的问题,如果你不考虑这个错误可能很难发现。 【参考方案1】:

标签main 似乎在.data 部分中。

这会导致不允许在.data 部分执行代码的系统出现分段错误。 (大多数现代系统映射 .data 具有读 + 写但没有 exec 权限。)

程序代码应该在.text 部分。 (读取+执行)

令人惊讶的是,在 GNU/Linux 系统上,手写 asm 通常会生成可执行文件 .data,除非您小心避免这种情况,因此这通常不是真正的问题:请参阅 Why data and stack segments are executable? 但将代码放入 @ 987654329@所在的位置可以让一些调试工具更好的工作。


您还需要从 main 调用 ret 或调用 exit(或进行 _exit 系统调用),这样执行就不会从 main 的末尾下降到接下来的任何字节。见What happens if there is no exit system call in an assembly program?

【讨论】:

这解决了我的问题!从来没有想过这样的事情会导致“段错误”......在我看来,段错误通常表明我在某处有一些未初始化的变量 @OneTwoThree:数据段内存映射有读/写但没有执行权限。因此,C 运行时启动代码在运行call main 指令时会导致段错误。内存页面的额外权限位是一项安全功能(“NX”)。【参考方案2】:

您需要正确终止程序,例如在 Linux x86_64 上通过调用 sys_exit 系统调用:

...
main:
     # assign array_words[0] to eax
     mov $0, %edi
     lea array_words(,%edi,4), %eax

     mov $60, %rax       # System-call "sys_exit"
     mov $0, %rdi        # exit code 0
     syscall

否则程序将继续执行最后一条指令之后的内存内容,这很可能在所有情况下都是无效指令(甚至是无效的内存位置)。

【讨论】:

或者因为这是main(不是_start),它是一个函数,所以你可以简单地ret。此外,在 x86-64 中,即使要将结果截断为 32 位,也应该使用 64 位地址大小,例如 mov $edi,0lea array_words(,%rdi,4), %raxlea array_words(,%rdi,4), %eax.

以上是关于.text .data 和 main 的分段错误(主要在 .data 部分)的主要内容,如果未能解决你的问题,请参考以下文章

全局写入时出现分段错误

循环分段错误

我应该使用哪些 gdb 命令来缩小标签“main”中出现分段错误的位置?

在进入 main() 之前出现分段错误 [关闭]

为啥 const int main = 195 会导致程序正常工作,但没有 const 会导致分段错误?

使用 pcl::ExtractIndices (pcl, ROS, catkin) 在 main 之前出现分段错误