go编译器生成的汇编代码中的这种模式是什么?

时间:2016-03-17 07:25:09

标签: assembly go

我在Linux内核中调试了一个无关紧要的问题,看到由主管管理的etcd进程反复出现页面错误异常并接收到SIGSEGV。

我很好奇并使用objdump反汇编程序,发现错误的amd64指令是:

89 04 25 00 00 00 00    mov    %eax,0x0

然后我看了一个hello world程序的反汇编。我在go编译器生成的代码中看到了一个非常常见的模式,即在函数结束时,在ret之后,sa 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>

这是一些玩法吗?如果是这样,它是如何工作的?我猜0x400c51它跳转到0x400cac,触发SIGSEGV,然后处理,然后下一条指令跳回0x400c53

1 个答案:

答案 0 :(得分:1)

我从Go开发者那里得到了一些答案:https://groups.google.com/forum/#!topic/golang-nuts/_7yio3ZfVBE

基本上,这种模式是过时实现中的零检查。引用的是Keith Randall的答案。

  

如果指针为nil,则跳转到生成a的指令   故障。那个错误用于启动nil ptr恐慌。

     

这是一个非常低效的代码序列。 jmps似乎永远不会出现   用过的。升级到更新的Go版本,您将看到它   改善。