[llvm-bugs] [Bug 28098] New: Inline assembly, instruction order and register clobbering on Aarch64

via llvm-bugs llvm-bugs at lists.llvm.org
Sun Jun 12 10:22:44 PDT 2016


https://llvm.org/bugs/show_bug.cgi?id=28098

            Bug ID: 28098
           Summary: Inline assembly, instruction order and register
                    clobbering on Aarch64
           Product: clang
           Version: 3.7
          Hardware: PC
                OS: Linux
            Status: NEW
          Severity: normal
          Priority: P
         Component: -New Bugs
          Assignee: unassignedclangbugs at nondot.org
          Reporter: the.arul at gmail.com
                CC: llvm-bugs at lists.llvm.org
    Classification: Unclassified

Created attachment 16521
  --> https://llvm.org/bugs/attachment.cgi?id=16521&action=edit
Source for example

The attached program should write out two strings, "A TEST!" and "Blow up!" but
the second write causes a segfault. Here's output from GDB:

   0x00000000004005c0 <+0>:     stp     x29, x30, [sp,#-16]!
   0x00000000004005c4 <+4>:     mov     x29, sp
   0x00000000004005c8 <+8>:     sub     sp, sp, #0x30
   0x00000000004005cc <+12>:    adrp    x8, 0x400000
   0x00000000004005d0 <+16>:    add     x8, x8, #0x6d8
   0x00000000004005d4 <+20>:    adrp    x9, 0x400000
   0x00000000004005d8 <+24>:    add     x9, x9, #0x460
   0x00000000004005dc <+28>:    adrp    x10, 0x400000
   0x00000000004005e0 <+32>:    add     x10, x10, #0x6d0
   0x00000000004005e4 <+36>:    stur    wzr, [x29,#-4]
   0x00000000004005e8 <+40>:    stur    w0, [x29,#-8]
   0x00000000004005ec <+44>:    stur    x1, [x29,#-16]
   0x00000000004005f0 <+48>:    str     x10, [sp,#24]
   0x00000000004005f4 <+52>:    str     x9, [sp,#16]
   0x00000000004005f8 <+56>:    ldr     x9, [sp,#24]
   0x00000000004005fc <+60>:    ldr     x10, [sp,#16]
   0x0000000000400600 <+64>:    mov     x0, x9
   0x0000000000400604 <+68>:    blr     x10
   0x0000000000400608 <+72>:    str     x9, [sp,#24]
   0x000000000040060c <+76>:    str     x10, [sp,#16]
   0x0000000000400610 <+80>:    mov     x0, x8
   0x0000000000400614 <+84>:    bl      0x400460 <puts at plt>
=> 0x0000000000400618 <+88>:    mov     w11, wzr
   0x000000000040061c <+92>:    str     w0, [sp,#12]
   0x0000000000400620 <+96>:    mov     w0, w11
   0x0000000000400624 <+100>:   mov     sp, x29
   0x0000000000400628 <+104>:   ldp     x29, x30, [sp],#16
   0x000000000040062c <+108>:   ret

Near the start of the function the x8 register is set as:

   0x00000000004005cc <+12>:    adrp    x8, 0x400000
   0x00000000004005d0 <+16>:    add     x8, x8, #0x6d8

Inspecting the combined address yields the valid string:

   (gdb) p (char *)(0x400000 + 0x6d8)
   $1 = 0x4006d8 "Blow up!"

However the indirect call to `puts` via inline assembly:

   0x0000000000400604 <+68>:    blr     x10

Mutates the x8 register before it's written out with the value of 64:

(gdb) b *0x0000000000400600
Breakpoint 2 at 0x400600
(gdb) r
Starting program: /opt/asm/test
Breakpoint 2, 0x0000000000400600 in main ()
(gdb) watch $x8 == 64
Watchpoint 3: $x8 == 64
(gdb) c
Continuing.
Watchpoint 3: $x8 == 64

Old value = 0
New value = 1
0x0000007fb7ebb3c8 in _IO_new_file_write () from /lib64/libc.so.6
(gdb) bt
#0  0x0000007fb7ebb3c8 in _IO_new_file_write () from /lib64/libc.so.6
#1  0x0000007fb7ebcb24 in __GI__IO_do_write () from /lib64/libc.so.6
#2  0x0000007fb7ebcf30 in __GI__IO_file_overflow () from /lib64/libc.so.6
#3  0x0000007fb7eb1c80 in puts () from /lib64/libc.so.6
#4  0x0000000000400608 in main ()

One way to work around this issue is adding x8 to the list of clobbered
registers:

        __asm__("MOV x0, %0         \n"
                "BLR %1             \n"
                : "+r"(str), "+r"(putsptr) :: "x0", "x8");

But this feels wrong, since the x8 register is defined by the ABI as "indirect
result location register", so technically any BLR instruction should clobber
it.
Note this wouldn't be an issue hadn't the instructions been rather aggressively
reordered, GCC 5.3.1 produces "more expected" result and works out of the box:

   0x00000000004005c0 <+0>:     stp     x29, x30, [sp,#-48]!
   0x00000000004005c4 <+4>:     mov     x29, sp
   0x00000000004005c8 <+8>:     str     w0, [x29,#28]
   0x00000000004005cc <+12>:    str     x1, [x29,#16]
   0x00000000004005d0 <+16>:    adrp    x0, 0x400000
   0x00000000004005d4 <+20>:    add     x0, x0, #0x6c0
   0x00000000004005d8 <+24>:    str     x0, [x29,#40]
   0x00000000004005dc <+28>:    adrp    x0, 0x400000
   0x00000000004005e0 <+32>:    add     x0, x0, #0x460
   0x00000000004005e4 <+36>:    str     x0, [x29,#32]
   0x00000000004005e8 <+40>:    ldr     x1, [x29,#40]
   0x00000000004005ec <+44>:    ldr     x0, [x29,#32]
   0x00000000004005f0 <+48>:    mov     x2, x1
   0x00000000004005f4 <+52>:    mov     x1, x0
   0x00000000004005f8 <+56>:    mov     x0, x2
   0x00000000004005fc <+60>:    blr     x1
   0x0000000000400600 <+64>:    str     x2, [x29,#40]
   0x0000000000400604 <+68>:    str     x1, [x29,#32]
   0x0000000000400608 <+72>:    adrp    x0, 0x400000
   0x000000000040060c <+76>:    add     x0, x0, #0x6c8
   0x0000000000400610 <+80>:    bl      0x400460 <puts at plt>
   0x0000000000400614 <+84>:    mov     w0, #0x0                        // #0
   0x0000000000400618 <+88>:    ldp     x29, x30, [sp],#48
   0x000000000040061c <+92>:    ret

-Pavel

-- 
You are receiving this mail because:
You are on the CC list for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-bugs/attachments/20160612/5a2d0789/attachment.html>


More information about the llvm-bugs mailing list