Subject: bug#48061: Unexpected result from a native-compiled function

From: Alan Mackenzie <[email-masked]>
Date: Tue, 27 Apr 2021 17:20:22 +0000

On Tue, Apr 27, 2021 at 14:49:31 +0000, Alan Mackenzie wrote:
> Hello, Emacs.

> In certain circumstances (see below for recipe), the natively compiled
> version of c-determine-limit-no-macro returns an invalid result, nil.
> In the same circumstances, the edebug instrumented version returns the
> correct result, a buffer position.

> So far I have tried M-x disassemble RET c-determine-limit-no-macro, but
> I wasn't able to follow the output (there were no symbols in the
> listing).

I've now managed to get a decent disassembly, and there is indeed a
missing machine instruction in the code which causes it to fail:

The function is:

#########################################################################
(defun c-determine-limit-no-macro (here org-start)
  ;; If HERE is inside a macro, and ORG-START is not also in the same macro,
  ;; return the beginning of the macro.  Otherwise return HERE.  Point is not
  ;; preserved by this function.
  (goto-char here)
  (let ((here-BOM (and (c-beginning-of-macro) (point))))
    (if (and here-BOM
             (not (eq (progn (goto-char org-start)
                             (and (c-beginning-of-macro) (point)))
                      here-BOM)))
        here-BOM
      here)))
#########################################################################

The register use in the compiled function is:

rbp     here
r12     org-start
r13     here-BOM

The disassembly (with some added notes) is this:

00000000000264f0 <F632d64657465726d696e652d6c696d69742d6e6f2d6d6163726f_c_determine_limit_no_macro_0>:
   264f0:       41 56                   push   %r14
   264f2:       41 55                   push   %r13
   264f4:       41 54                   push   %r12
   264f6:       49 89 f4                mov    %rsi,%r12   org-start
   264f9:       55                      push   %rbp
   264fa:       48 89 fd                mov    %rdi,%rbp   here
   264fd:       53                      push   %rbx
   264fe:       48 83 ec 20             sub    $0x20,%rsp
   26502:       64 48 8b 04 25 28 00    mov    %fs:0x28,%rax
   26509:       00 00
   2650b:       48 89 44 24 18          mov    %rax,0x18(%rsp)
   26510:       48 8b 05 d1 2a 27 00    mov    0x272ad1(%rip),%rax        # 298fe8 <_DYNAMIC+0x1f8>
   26517:       48 8b 18                mov    (%rax),%rbx
   2651a:       ff 93 b8 14 00 00       callq  *0x14b8(%rbx)        goto-char
   26520:       48 8d 74 24 08          lea    0x8(%rsp),%rsi
   26525:       bf 01 00 00 00          mov    $0x1,%edi
   2652a:       4c 8b 35 af 2a 27 00    mov    0x272aaf(%rip),%r14        # 298fe0 <_DYNAMIC+0x1f0>
   26531:       49 8b 86 c8 00 00 00    mov    0xc8(%r14),%rax
   26538:       48 89 44 24 08          mov    %rax,0x8(%rsp)
   2653d:       ff 93 08 1a 00 00       callq  *0x1a08(%rbx)      c-beginning-of-macro
   26543:       48 85 c0                test   %rax,%rax
   26546:       74 52                   je     2659a <F632d64657465726d696e652d6c696d69742d6e6f2d6d6163726f_c_determine_limit_no_macro_0+0xaa>
   26548:       ff 93 68 14 00 00       callq  *0x1468(%rbx)      point
   2654e:       49 89 c5                mov    %rax,%r13        here-BOM
   26551:       48 85 c0                test   %rax,%rax
   26554:       74 44                   je     2659a <F632d64657465726d696e652d6c696d69742d6e6f2d6d6163726f_c_determine_limit_no_macro_0+0xaa>
   26556:       4c 89 e7                mov    %r12,%rdi         org-start
   26559:       ff 93 b8 14 00 00       callq  *0x14b8(%rbx)        goto-char
   2655f:       bf 01 00 00 00          mov    $0x1,%edi
   26564:       48 8d 74 24 10          lea    0x10(%rsp),%rsi
   26569:       49 8b 86 c8 00 00 00    mov    0xc8(%r14),%rax
   26570:       48 89 44 24 10          mov    %rax,0x10(%rsp)
   26575:       ff 93 08 1a 00 00       callq  *0x1a08(%rbx)       c-beginning-of-macro
   2657b:       48 89 c7                mov    %rax,%rdi
   2657e:       48 85 c0                test   %rax,%rax
   26581:       74 09                   je     2658c <F632d64657465726d696e652d6c696d69742d6e6f2d6d6163726f_c_determine_limit_no_macro_0+0x9c>
   26583:       ff 93 68 14 00 00       callq  *0x1468(%rbx)       point
   26589:       48 89 c7                mov    %rax,%rdi
   2658c:       4c 89 ee                mov    %r13,%rsi         here-BOM
   2658f:       ff 93 60 27 00 00       callq  *0x2760(%rbx)       eq
   26595:       48 85 c0                test   %rax,%rax                                  <========================================================
   26598:       74 03                   je     2659d <F632d64657465726d696e652d6c696d69742d6e6f2d6d6163726f_c_determine_limit_no_macro_0+0xad>
   2659a:       48 89 e8                mov    %rbp,%rax         here
   2659d:       48 8b 54 24 18          mov    0x18(%rsp),%rdx
   265a2:       64 48 2b 14 25 28 00    sub    %fs:0x28,%rdx
   265a9:       00 00
   265ab:       75 0d                   jne    265ba <F632d64657465726d696e652d6c696d69742d6e6f2d6d6163726f_c_determine_limit_no_macro_0+0xca>
   265ad:       48 83 c4 20             add    $0x20,%rsp
   265b1:       5b                      pop    %rbx
   265b2:       5d                      pop    %rbp
   265b3:       41 5c                   pop    %r12
   265b5:       41 5d                   pop    %r13
   265b7:       41 5e                   pop    %r14
   265b9:       c3                      retq
   265ba:       e8 41 12 fe ff          callq  7800 <__stack_chk_fail@plt>
   265bf:       90                      nop

After the indicated line (0x26595), when 0x0 (nil) is in rax (i.e. the
`eq' function has returned nil) the result of the function should be
here-BOM, i.e. r13.  There is no instruction

    mov %r13,%rax

to effect this return.  Instead, rax is still holding nil, and this is
falsely returned.

> -- 
> Alan Mackenzie (Nuremberg, Germany).