我在Linux内核中调试了一个无关紧要的问题,看到由主管管理的etcd进程反复出现页面错误异常并接收到SIGSEGV.
我好奇并使用objdump来反汇编程序,并发现错误的amd64指令是:
89 04 25 00 00 00 00 mov %eax,0x0
Run Code Online (Sandbox Code Playgroud)
然后我看了一个hello world程序的反汇编.我在go编译器生成的代码中看到了一个非常常见的模式,即在函数结束时ret,mov紧接着,然后jmp返回函数.例如,
0000000000400c00 <main.main>:
400c00: 64 48 8b 0c 25 f0 ff mov %fs:0xfffffffffffffff0,%rcx
400c07: ff ff
...
400c4b: 48 83 7c 24 48 00 cmpq $0x0,0x48(%rsp)
400c51: 74 59 je 400cac <main.main+0xac>
400c53: 48 c7 04 24 c0 fc 47 movq $0x47fcc0,(%rsp)
400c5a: 00
...
400cab: c3 retq
400cac: 89 04 25 00 00 00 00 mov %eax,0x0
400cb3: eb 9e jmp 400c53 <main.main+0x53>
Run Code Online (Sandbox Code Playgroud)
这是一些玩法吗?如果是这样,它是如何工作的?我猜0x400c51它跳转到0x400cac,触发a SIGSEGV,处理然后下一条指令跳回0x400c53.
我从 Go 开发者那里得到了一些答案: https://groups.google.com/forum/#! topic/golang-nuts/_7yio3ZfVBE
基本上,这种模式是过时实现中的 nil 检查。引用的是 Keith Randall 的回答。
如果指针为零,则跳转到产生错误的指令。该错误用于启动 nil ptr 恐慌。
这是一个非常低效的代码序列。jmp 似乎从未被使用过。升级到最新的 Go 版本,您会发现它已得到改进。
| 归档时间: |
|
| 查看次数: |
221 次 |
| 最近记录: |