linux - 为什么 gcc 在调用 “halt” 之后在程序中放置 “main” 指令?

标签 linux gcc assembly glibc

在 Linux/i386 系统上查看由 gcc 生成的 elf 可执行文件时,它似乎总是在调用“main”之后和“nop”填充之前放置一个暂停指令(0xf4),例如:

│ ....... ! entrypoint:
│ ....... !   xor         ebp, ebp
│ 80482e2 !   pop         esi
│ 80482e3 !   mov         ecx, esp*emphasized text*
│ 80482e5 !   and         esp, 0fffffff0h
│ 80482e8 !   push        eax
│ 80482e9 !   push        esp
│ 80482ea !   push        edx
│ 80482eb !   push        __libc_csu_fini
│ 80482f0 !   push        __libc_csu_init
│ 80482f5 !   push        ecx
│ 80482f6 !   push        esi
│ 80482f7 !   push        main
│ 80482fc !   call        wrapper_804a004_80482c4
│ 8048301 !   hlt                                      <--- halt instruction
│ 8048302 !   nop
│ 8048303 !   nop
│ 8048304 !   nop
               ⋮

这样做的目的是什么? 永远不应达到此代码。这是某种保障措施吗?

最佳答案

main返回后会调用exit。 hlt 存在以防系统的退出版本不会立即停止进程的执行。在用户态下,会造成保护错误,从而杀死进程。如果该进程由于某种原因在 ring 0 中运行,它只会停止处理器直到下一个中​​断,这将有望触发操作系统删除该进程。在设计为在 ring 0 中运行的进程中,通常在 hlt 之后有一个 jmp 指令,这将导致 hlt 反复执行,直到进程终止。

关于linux - 为什么 gcc 在调用 “halt” 之后在程序中放置 “main” 指令?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5213466/

相关文章:

c++ - 转换持有多态类型的模板时的未定义行为

c - 在调用者的返回序列中跳过函数

assembly - (MIPS)某些汇编指令是否比其他指令更快?

linux - 如何将 MCP23017 与 MCP3008 一起用于 Raspberry Pi 的 I2C 电压传感器?

linux - 提取新代码后创建本地目录以编辑代码

gcc - 编译glib 2.48无法识别具有utf支持的pcre

assembly - push myVar , push [myVar] 和 push OFFSET myVar 之间的区别

linux - 无法将 C++ 扩展上传到 Colab

c++ - 使用 addch 获得意想不到的字符

c - C/GCC 4.6.3 中的 union 填充值