在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
⋮
这是为了什么目的? 永远不应该达到此代码。这是某种保障吗?
答案 0 :(得分:11)
主要返回后,将调用exit。如果系统的exit版本没有立即停止执行进程,那么hlt就在那里。在用户模式下,它将导致保护错误,这将导致进程终止。如果进程由于某种原因在环0中运行,它将停止处理器直到下一个中断,这将有希望触发操作系统删除进程。在设计为在环0中运行的进程中,在hlt之后通常会有一条jmp指令,这将导致hlt反复执行,直到进程终止。
答案 1 :(得分:3)
我认为它是一种保护措施,可能实际上并不起作用。例如,hlt是一个priveldged指令,这意味着它将在环3(大多数应用程序运行)中执行时抛出异常。最好的情况是,它可能对内核代码很有用,但如果启用了中断,那么hlt将只持续到处理器获得中断,然后处理器将继续执行nop填充。
答案 2 :(得分:0)
你是对的 - 永远不应该达到这个代码,并且可能在开发时作为保护措施。有堆栈操作来防止回叫。