0

This cppreference example fails with Error: invalid operands (*UND* and *UND* sections) for %'` on g++ 11.1.0 on my Archlinux box, but not on coliru. Why?

The file name is _1h6.cpp:

$ g++ _1h6.cpp -S && as _1h6.s # same error as g++ _1h6.cpp
_1h6.s: Assembler messages:
_1h6.s:11: Error: invalid operands (*UND* and *UND* sections) for `%'
_1h6.cpp:29: Error: invalid operands (*UND* and *UND* sections) for `%'
_1h6.cpp:30: Error: invalid operands (*UND* and *UND* sections) for `%'

Here the C++ code:

#include <iostream>
extern "C" int func();
// the definition of func is written in assembly language
// raw string literal could be very useful
asm(R"(
.globl func
    .type func, @function
    func:
    .cfi_startproc
    movl $7, %eax
    ret
    .cfi_endproc
)");
int main()
{
    int n = func();
    // extended inline assembly
    asm ("leal (%0,%0,4),%0"
         : "=r" (n)
         : "0" (n));
    std::cout << "7*5 = " << n << std::endl; // flush is intentional
    // standard inline assembly
    asm ("movq $60, %rax\n\t" // the exit syscall number on Linux
         "movq $2,  %rdi\n\t" // this program returns 2
         "syscall");
}

UND refers to a temporary elf section (undefined) for references without target. Could my g++ internally link different libraries than coliru? I use the same command as coliru:

g++ -std=c++20 -pthread  -O2 -Wall -Wextra -pedantic -pthread -pedantic-errors _1h6.cpp -lm  -latomic -lstdc++fs  && ./a.out

When I use -S to create the assembly, the error happens with as _1h6.s. Here the -S output:

    .file   "_1h6.cpp"
    .text
    .local  _ZStL8__ioinit
    .comm   _ZStL8__ioinit,1,1
#APP
    
.globl func
    .type func, @function
    func:
    .cfi_startproc
    movl $7, %eax
    ret
    .cfi_endproc

    .section    .rodata
.LC0:
    .string "7*5 = "
#NO_APP
    .text
    .globl  main
    .type   main, @function
main:
.LFB1729:
    .cfi_startproc
    pushq   %rbp
    .cfi_def_cfa_offset 16
    .cfi_offset 6, -16
    movq    %rsp, %rbp
    .cfi_def_cfa_register 6
    subq    $16, %rsp
    call    func@PLT
    movl    %eax, -4(%rbp)
    movl    -4(%rbp), %eax
#APP
# 27 "_1h6.cpp" 1
    leal (%eax,%eax,4),%eax
# 0 "" 2
#NO_APP
    movl    %eax, -4(%rbp)
    leaq    .LC0(%rip), %rax
    movq    %rax, %rsi
    leaq    _ZSt4cout(%rip), %rax
    movq    %rax, %rdi
    call    _ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc@PLT
    movq    %rax, %rdx
    movl    -4(%rbp), %eax
    movl    %eax, %esi
    movq    %rdx, %rdi
    call    _ZNSolsEi@PLT
    movq    _ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_@GOTPCREL(%rip), %rdx
    movq    %rdx, %rsi
    movq    %rax, %rdi
    call    _ZNSolsEPFRSoS_E@PLT
#APP
# 32 "_1h6.cpp" 1
    movq $60, %rax
    movq $2,  %rdi
    syscall
# 0 "" 2
#NO_APP
    movl    $0, %eax
    leave
    .cfi_def_cfa 7, 8
    ret
    .cfi_endproc
.LFE1729:
    .size   main, .-main
    .type   _Z41__static_initialization_and_destruction_0ii, @function
_Z41__static_initialization_and_destruction_0ii:
.LFB2232:
    .cfi_startproc
    pushq   %rbp
    .cfi_def_cfa_offset 16
    .cfi_offset 6, -16
    movq    %rsp, %rbp
    .cfi_def_cfa_register 6
    subq    $16, %rsp
    movl    %edi, -4(%rbp)
    movl    %esi, -8(%rbp)
    cmpl    $1, -4(%rbp)
    jne .L5
    cmpl    $65535, -8(%rbp)
    jne .L5
    leaq    _ZStL8__ioinit(%rip), %rax
    movq    %rax, %rdi
    call    _ZNSt8ios_base4InitC1Ev@PLT
    leaq    __dso_handle(%rip), %rax
    movq    %rax, %rdx
    leaq    _ZStL8__ioinit(%rip), %rax
    movq    %rax, %rsi
    movq    _ZNSt8ios_base4InitD1Ev@GOTPCREL(%rip), %rax
    movq    %rax, %rdi
    call    __cxa_atexit@PLT
.L5:
    nop
    leave
    .cfi_def_cfa 7, 8
    ret
    .cfi_endproc
.LFE2232:
    .size   _Z41__static_initialization_and_destruction_0ii, .-_Z41__static_initialization_and_destruction_0ii
    .type   _GLOBAL__sub_I_main, @function
_GLOBAL__sub_I_main:
.LFB2233:
    .cfi_startproc
    pushq   %rbp
    .cfi_def_cfa_offset 16
    .cfi_offset 6, -16
    movq    %rsp, %rbp
    .cfi_def_cfa_register 6
    movl    $65535, %esi
    movl    $1, %edi
    call    _Z41__static_initialization_and_destruction_0ii
    popq    %rbp
    .cfi_def_cfa 7, 8
    ret
    .cfi_endproc
.LFE2233:
    .size   _GLOBAL__sub_I_main, .-_GLOBAL__sub_I_main
    .section    .init_array,"aw"
    .align 8
    .quad   _GLOBAL__sub_I_main
    .hidden __dso_handle
    .ident  "GCC: (GNU) 11.1.0"
    .section    .note.GNU-stack,"",@progbits

As the error comes from as, it is a binutils problem. as --version:

GNU assembler (GNU Binutils) 2.36.1
Copyright (C) 2021 Free Software Foundation, Inc.
This program is free software; you may redistribute it under the terms of
the GNU General Public License version 3 or later.
This program has absolutely no warranty.
This assembler was configured for a target of `x86_64-pc-linux-gnu'.

Similar questions did not help:

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
Roland Puntaier
  • 3,250
  • 30
  • 35
  • Stack Overflow questions must be self-contained. Please post the exact code you tried inline into your question. Also post the assembly output obtained by passing `-S` to the compiler. – fuz Jun 26 '21 at 08:37
  • What is the complete error message (including the file name and the line number at the start) – Michael Petch Jun 26 '21 at 10:01
  • If you can't assemble that then it sounds like a binutils problem. Works fine here with 2.28 and 2.33.1. Can you mark the line that has the error? – Jester Jun 26 '21 at 11:25
  • Please show us the output of `as --version`. – Florian Weimer Jun 26 '21 at 12:27
  • 1
    Works with G++11.0 on https://godbolt.org/z/fx6EzT3En. Are you sure you didn't accidentally leave a space after a `%` somewhere, and/or omit a comma? `7 % eax` would explain the error message. Possibly you forgot to save before rebuilding, so your copy/pasted [mcve] doesn't match your local testing? I also copy-pasted your asm output into `foo.s` on my local machine (Arch Linux with GNU Binutils 2.35.1), and it assembled fine. So that rules out compiling a bad version of your C++ source. – Peter Cordes Jun 26 '21 at 15:03
  • Also BTW, `leal (%q0, %q0, 4), %0` would be more efficient. There's never a reason to use 32-bit address-size with LEA, except to make the instruction longer if that helps alignment of later instructions.. – Peter Cordes Jun 26 '21 at 15:06
  • IDK what gas version Godbolt has, but your asm output also assembles on https://godbolt.org/z/nEKPEbdsP with language = assembly. Line 11 is `movl $7, %eax` which does have a `%`, but it's correct and totally normal AT&T syntax. I don't see how anything could make that line be interpreted as `.intel_syntax noprefix`, and that produces a different error anyway ("no such instruction") – Peter Cordes Jun 26 '21 at 15:09
  • Do you maybe have an alias set up for `as` that adds some command-line options? `type -a as` – Peter Cordes Jun 26 '21 at 15:13
  • 1
    Oh. I just realized, there must be a different kind of space before the `%`. Indeed it was not `\x20`, but `\x00a0`. I had automatically extracted the example from the HTML. I pasted, but I think Stackoverflow does some character sanitizing. I pasted back onto my machine and it worked. Thanks @peter-cordes for the hints. – Roland Puntaier Jun 26 '21 at 16:52
  • `00a0` was what vim showed, actually it was `\xc2\xa0`. – Roland Puntaier Jun 26 '21 at 17:08

1 Answers1

2

The code, which lead to the error, was automatically extracted from HTML and it was not visible that the space was not a space. Something that looks like a space in the editor might not be a space. Here \xc2\xa0 was before the %, which made as produce the error.

Roland Puntaier
  • 3,250
  • 30
  • 35