Bug 98667 - gcc generates endbr32 invalid opcode on -march=i486
Summary: gcc generates endbr32 invalid opcode on -march=i486
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: target (show other bugs)
Version: 9.3.0
: P3 normal
Target Milestone: 11.0
Assignee: Not yet assigned to anyone
URL:
Keywords: wrong-code
Depends on: 70454
Blocks:
  Show dependency treegraph
 
Reported: 2021-01-14 01:24 UTC by Matthew Whitehead
Modified: 2021-10-21 19:14 UTC (History)
4 users (show)

See Also:
Host:
Target: i?86-*-*
Build:
Known to work:
Known to fail:
Last reconfirmed: 2021-01-14 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Matthew Whitehead 2021-01-14 01:24:13 UTC
Compiling the 'eix' program with gcc 9.3.0 and the '-march=i486' generated an 'endbr32' opcode. This is an undefined opcode on an i486.


# /usr/bin/gdb /usr/bin/eix
GNU gdb (Gentoo 10.1 vanilla) 10.1
...
Reading symbols from /usr/bin/eix...
Reading symbols from /usr/lib/debug//usr/bin/eix.debug...
(gdb) run
Starting program: /usr/bin/eix

Program received signal SIGILL, Illegal instruction.
_GLOBAL__sub_I_spaces () at eixTk/stringutils.cc:686
686     }

(gdb) disassemble _GLOBAL__sub_I_spaces
Dump of assembler code for function _GLOBAL__sub_I_spaces():
=> 0x004208e0 <+0>:     endbr32
   0x004208e4 <+4>:     push   %esi
   0x004208e5 <+5>:     push   %ebx
   0x004208e6 <+6>:     sub    $0xc,%esp
   0x004208e9 <+9>:     call   0x420d30 <__x86.get_pc_thunk.bx>
   0x004208ee <+14>:    add    $0x17e712,%ebx
   0x0042091e <+62>:    add    $0x14,%esp
   0x00420921 <+65>:    pop    %ebx
   0x00420922 <+66>:    pop    %esi
   0x00420923 <+67>:    ret    

(gdb) list
681                     if(likely(isutf8firstgyte(t[i]))) {
682                             ++len;
683                     }
684             }
685             return len;
686     }
Comment 1 Matthew Whitehead 2021-01-14 01:28:09 UTC
Here is the full set of compiler flags used.

readelf --string-dump='.GCC.command.line' /usr/lib/debug/$( which eix ).debug  

String dump of section '.GCC.command.line':
  [     0]  -I .
  [     5]  -I ..
  [     b]  -D_GNU_SOURCE
  [    19]  -D HAVE_CONFIG_H
  [    2a]  -D SYSCONFDIR="/etc"
  [    3f]  -D LOCALEDIR="/usr/share/locale"
  [    60]  -D _FORTIFY_SOURCE=2
  [    75]  various/drop_permissions.cc
  [    91]  -march=i486
  [    9d]  -auxbase-strip various/drop_permissions.o
  [    c7]  -g
  [    ca]  -ggdb
  [    d0]  -O2
  [    d4]  -fdata-sections
  [    e4]  -ffunction-sections
  [    f8]  -fcf-protection=full
  [   10d]  -fstack-clash-protection
  [   126]  -frecord-gcc-switches
  [   13c]  eixTk/compare.cc
  [   14d]  -auxbase-strip eixTk/compare.o
  [   16c]  eixTk/formated.cc
  [   17e]  -auxbase-strip eixTk/formated.o
  [   19e]  eixTk/stringutils.cc
  [   1b3]  -auxbase-strip eixTk/stringutils.o
  [   1d6]  eixTk/ansicolor.cc
  [   1e9]  -auxbase-strip eixTk/ansicolor.o
  [   20a]  eixTk/argsreader.cc
  [   21e]  -auxbase-strip eixTk/argsreader.o
  [   240]  eixTk/parseerror.cc
  [   254]  -auxbase-strip eixTk/parseerror.o
  [   276]  eixTk/regexp.cc
  [   286]  -auxbase-strip eixTk/regexp.o
  [   2a4]  eixTk/sysutils.cc
  [   2b6]  -auxbase-strip eixTk/sysutils.o
  [   2d6]  eixTk/filenames.cc
  [   2e9]  -auxbase-strip eixTk/filenames.o
  [   30a]  eixTk/utils.cc
  [   319]  -auxbase-strip eixTk/utils.o
  [   336]  eixTk/varsreader.cc
  [   34a]  -auxbase-strip eixTk/varsreader.o
  [   36c]  database/io.cc
  [   37b]  -auxbase-strip database/io.o
  [   398]  database/io_header.cc
  [   3ae]  -auxbase-strip database/io_header.o
  [   3d2]  database/header.cc
  [   3e5]  -auxbase-strip database/header.o
  [   406]  database/header_portage.cc
  [   421]  -auxbase-strip database/header_portage.o
  [   44a]  database/io_portage.cc
  [   461]  -auxbase-strip database/io_portage.o
  [   486]  database/package_reader.cc
  [   4a1]  -auxbase-strip database/package_reader.o
  [   4ca]  portage/conf/portagesettings.cc
  [   4ea]  -auxbase-strip portage/conf/portagesettings.o
  [   518]  portage/conf/cascadingprofile.cc
  [   539]  -auxbase-strip portage/conf/cascadingprofile.o
  [   568]  eixTk/stringlist.cc
  [   57c]  -auxbase-strip eixTk/stringlist.o
  [   59e]  portage/mask.cc
  [   5ae]  -auxbase-strip portage/mask.o
  [   5cc]  portage/mask_list.cc
  [   5e1]  -auxbase-strip portage/mask_list.o
  [   604]  portage/depend.cc
  [   616]  -auxbase-strip portage/depend.o
  [   636]  portage/basicversion.cc
  [   64e]  -auxbase-strip portage/basicversion.o
  [   674]  portage/eapi.cc
  [   684]  -auxbase-strip portage/eapi.o
  [   6a2]  portage/extendedversion.cc
  [   6bd]  -auxbase-strip portage/extendedversion.o
  [   6e6]  portage/extendedversion_bin.cc
  [   705]  -auxbase-strip portage/extendedversion_bin.o
  [   732]  portage/instversion.cc
  [   749]  -auxbase-strip portage/instversion.o
  [   76e]  portage/package.cc
  [   781]  -auxbase-strip portage/package.o
  [   7a2]  portage/package_best.cc
  [   7ba]  -auxbase-strip portage/package_best.o
  [   7e0]  portage/packagesets.cc
  [   7f7]  -auxbase-strip portage/packagesets.o
  [   81c]  portage/vardbpkg.cc
  [   830]  -auxbase-strip portage/vardbpkg.o
  [   852]  portage/packagetree.cc
  [   869]  -auxbase-strip portage/packagetree.o
  [   88e]  portage/keywords.cc
  [   8a2]  -auxbase-strip portage/keywords.o
  [   8c4]  portage/overlay_bin.cc
  [   8db]  -auxbase-strip portage/overlay_bin.o
  [   900]  portage/overlay.cc
  [   913]  -auxbase-strip portage/overlay.o
  [   934]  portage/set_stability.cc
  [   94d]  -auxbase-strip portage/set_stability.o
  [   974]  portage/version.cc
  [   987]  -auxbase-strip portage/version.o
  [   9a8]  eixrc/eixrc.cc
  [   9b7]  -auxbase-strip eixrc/eixrc.o
  [   9d4]  eixrc/global.cc
  [   9e4]  -auxbase-strip eixrc/global.o
  [   a02]  eixrc/globals.cc
  [   a13]  -auxbase-strip eixrc/globals.o
  [   a32]  eixrc/eixrc_portage.cc
  [   a49]  -auxbase-strip eixrc/eixrc_portage.o
  [   a6e]  eixTk/outputstring.cc
  [   a84]  -auxbase-strip eixTk/outputstring.o
  [   aa8]  eixTk/stringlist_output.cc
  [   ac3]  -auxbase-strip eixTk/stringlist_output.o
  [   aec]  portage/version_output.cc
  [   b06]  -auxbase-strip portage/version_output.o
  [   b2e]  output/formatstring.cc
  [   b45]  -auxbase-strip output/formatstring.o
  [   b6a]  output/formatstring-print.cc
  [   b87]  -auxbase-strip output/formatstring-print.o
  [   bb2]  eix.cc
  [   bb9]  -auxbase-strip eix.o
  [   bce]  various/cli.cc
  [   bdd]  -auxbase-strip various/cli.o
  [   bfa]  output/print-proto.cc
  [   c10]  -auxbase-strip output/print-proto.o
  [   c34]  output/print-xml.cc
  [   c48]  -auxbase-strip output/print-xml.o
  [   c6a]  search/levenshtein.cc
  [   c80]  -auxbase-strip search/levenshtein.o
  [   ca4]  search/algorithms.cc
  [   cb9]  -auxbase-strip search/algorithms.o
  [   cdc]  search/matchtree.cc
  [   cf0]  -auxbase-strip search/matchtree.o
  [   d12]  search/packagetest.cc
  [   d28]  -auxbase-strip search/packagetest.o
  [   d4c]  search/packagetest_default.cc
  [   d6a]  -auxbase-strip search/packagetest_default.o
  [   d96]  search/nowarn.cc
  [   da7]  -auxbase-strip search/nowarn.o
  [   dc6]  eixTk/ansicolor_print.cc
  [   ddf]  -auxbase-strip eixTk/ansicolor_print.o
  [   e06]  eix-diff.cc
  [   e12]  -auxbase-strip eix-diff.o
  [   e2c]  eix-update.cc
  [   e3a]  -auxbase-strip eix-update.o
  [   e56]  eixTk/percentage.cc
  [   e6a]  -auxbase-strip eixTk/percentage.o
  [   e8c]  eixTk/statusline.cc
  [   ea0]  -auxbase-strip eixTk/statusline.o
  [   ec2]  cache/cachetable.cc
  [   ed6]  -auxbase-strip cache/cachetable.o
  [   ef8]  cache/common/assign_reader.cc
  [   f16]  -auxbase-strip cache/common/assign_reader.o
  [   f42]  cache/common/ebuild_exec.cc
  [   f5e]  -auxbase-strip cache/common/ebuild_exec.o
  [   f88]  cache/common/flat_reader.cc
  [   fa4]  -auxbase-strip cache/common/flat_reader.o
  [   fce]  cache/common/selectors.cc
  [   fe8]  -auxbase-strip cache/common/selectors.o
  [  1010]  cache/base.cc
  [  101e]  -auxbase-strip cache/base.o
  [  103a]  cache/eixcache/eixcache.cc
  [  1055]  -auxbase-strip cache/eixcache/eixcache.o
  [  107e]  cache/metadata/metadata.cc
  [  1099]  -auxbase-strip cache/metadata/metadata.o
  [  10c2]  cache/parse/parse.cc
  [  10d7]  -auxbase-strip cache/parse/parse.o
  [  10fa]  cache/sqlite/sqlite.cc
  [  1111]  -auxbase-strip cache/sqlite/sqlite.o
  [  1136]  eixTk/md5.cc
  [  1143]  -auxbase-strip eixTk/md5.o
  [  115e]  masked-packages.cc
  [  1171]  -auxbase-strip masked-packages.o
  [  1192]  versionsort.cc
  [  11a1]  -auxbase-strip versionsort.o
  [  11be]  eix-header.cc
  [  11cc]  -auxbase-strip eix-header.o
  [  11e8]  eix-drop-permissions.cc
  [  1200]  -auxbase-strip eix-drop-permissions.o
  [  1226]  main/main_all_tools.cc
  [  123d]  -auxbase-strip main/main_all_tools.o
  [  1262]  cache/cache_map.cc
  [  1275]  -auxbase-strip cache/cache_map.o
Comment 2 Andrew Pinski 2021-01-14 07:28:12 UTC
Is this directly on a i486 box or VirtualBox?  VirtualBox might have a bug.
Comment 3 Matthew Whitehead 2021-01-14 11:53:47 UTC
This is on an actual first generation i486DX 40MHz system I use to test for code issues exactly like this case.
Comment 4 Matthew Whitehead 2021-01-14 13:22:41 UTC
It looks like /usr/bin/gdb 10.1 also has this opcode in it:

objdump -D /usr/bin/gdb | grep -B6 -A6 endbr32 

  60d7b5:       3f                      aas    
  60d7b6:       1a 3b                   sbb    (%ebx),%bh
  60d7b8:       2a 32                   sub    (%edx),%dh
  60d7ba:       24 22                   and    $0x22,%al
  60d7bc:       00 00                   add    %al,(%eax)
  60d7be:       00 00                   add    %al,(%eax)
  60d7c0:       f3 0f 1e fb             endbr32 
  60d7c4:       ff a3 00 00 00 00       jmp    *0x0(%ebx)
  60d7ca:       66 0f 1f 44 00 00       nopw   0x0(%eax,%eax,1)
  60d7d0:       f3 0f 1e fb             endbr32 
  60d7d4:       ff 25 00 00 00 00       jmp    *0x0
  60d7da:       66 0f 1f 44 00 00       nopw   0x0(%eax,%eax,1)
  60d7e0:       ff b3 04 00 00 00       pushl  0x4(%ebx)
  60d7e6:       ff a3 08 00 00 00       jmp    *0x8(%ebx)
  60d7ec:       0f 1f 40 00             nopl   0x0(%eax)
  60d7f0:       f3 0f 1e fb             endbr32 
  60d7f4:       68 00 00 00 00          push   $0x0
  60d7f9:       e9 00 00 00 00          jmp    60d7fe <_IO_stdin_used@@Base+0xd77fa>
  60d7fe:       66 90                   xchg   %ax,%ax
  60d800:       ff 35 00 00 00 00       pushl  0x0
  60d806:       ff 25 00 00 00 00       jmp    *0x0
  60d80c:       0f 1f 40 00             nopl   0x0(%eax)

i686-pentium4-mpentium4-lenovo /usr/lib/debug/usr/bin # /usr/bin/gdb --version 
GNU gdb (Gentoo 10.1 vanilla) 10.1
Copyright (C) 2020 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

I will provide the gcc compile switches if asked, but it is long: 2156 items.
Comment 5 Jakub Jelinek 2021-01-14 13:29:13 UTC
I guess to stay compatible with such CPUs one would need to disable CET completely.
Pentium II (or whatever is the oldest that supports it):
https://stackoverflow.com/questions/56120231/how-do-old-cpus-execute-the-new-endbr64-and-endbr32-instructions
treat it as nops, which is the expected behavior on non-CET enabled hw.
Comment 6 Richard Biener 2021-01-14 14:04:13 UTC
It probably makes sense to disable CET by default when GCC is configured to "less" than i686-linux (definitely for i386 and i486, not sure about i586).
Thus change the regexps in config/cet.m4 to not include those for =auto
at least.
Comment 7 H.J. Lu 2021-01-14 14:07:26 UTC
A patch is posted at

https://gcc.gnu.org/pipermail/gcc-patches/2021-January/563478.html
Comment 8 H.J. Lu 2021-01-14 14:08:59 UTC
(In reply to Richard Biener from comment #6)
> It probably makes sense to disable CET by default when GCC is configured to
> "less" than i686-linux (definitely for i386 and i486, not sure about i586).
> Thus change the regexps in config/cet.m4 to not include those for =auto
> at least.

config/cet.m4 is OK:

ENDBR32 is NOP on SSE2 processors:

        # Check if target supports multi-byte NOPs
        # and if compiler and assembler support CET.
        AC_COMPILE_IFELSE(
         [AC_LANG_PROGRAM(
          [],
          [
#if !defined(__SSE2__)
#error target does not support multi-byte NOPs
#else
asm ("setssbsy");
#endif
          ])],
         [enable_cet=yes],
         [enable_cet=no])
        ;;
Comment 9 GCC Commits 2021-01-14 15:43:10 UTC
The master branch has been updated by H.J. Lu <hjl@gcc.gnu.org>:

https://gcc.gnu.org/g:77d372abec0fbf2cfe922e3140ee3410248f979e

commit r11-6672-g77d372abec0fbf2cfe922e3140ee3410248f979e
Author: H.J. Lu <hjl.tools@gmail.com>
Date:   Thu Jan 14 05:56:46 2021 -0800

    x86: Error on -fcf-protection with incompatible target
    
    -fcf-protection with CF_BRANCH inserts ENDBR32 at function entries.
    ENDBR32 is NOP only on 64-bit processors and 32-bit TARGET_CMOV
    processors.  Issue an error for -fcf-protection with CF_BRANCH when
    compiling for 32-bit non-TARGET_CMOV targets.
    
    gcc/
    
            PR target/98667
            * config/i386/i386-options.c (ix86_option_override_internal):
            Issue an error for -fcf-protection with CF_BRANCH when compiling
            for 32-bit non-TARGET_CMOV targets.
    
    gcc/testsuite/
    
            PR target/98667
            * gcc.target/i386/pr98667-1.c: New file.
            * gcc.target/i386/pr98667-2.c: Likewise.
            * gcc.target/i386/pr98667-3.c: Likewise.
Comment 10 H.J. Lu 2021-01-14 15:45:31 UTC
(In reply to Matthew Whitehead from comment #1)
> Here is the full set of compiler flags used.
> 
> readelf --string-dump='.GCC.command.line' /usr/lib/debug/$( which eix
> ).debug  
> 
> String dump of section '.GCC.command.line':
>   [     0]  -I .
>   [     5]  -I ..
>   [     b]  -D_GNU_SOURCE
>   [    19]  -D HAVE_CONFIG_H
>   [    2a]  -D SYSCONFDIR="/etc"
>   [    3f]  -D LOCALEDIR="/usr/share/locale"
>   [    60]  -D _FORTIFY_SOURCE=2
>   [    75]  various/drop_permissions.cc
>   [    91]  -march=i486
>   [    9d]  -auxbase-strip various/drop_permissions.o
>   [    c7]  -g
>   [    ca]  -ggdb
>   [    d0]  -O2
>   [    d4]  -fdata-sections
>   [    e4]  -ffunction-sections
>   [    f8]  -fcf-protection=full
>

Please remove -fcf-protection=full.
Comment 11 Matthew Whitehead 2021-01-15 13:26:51 UTC
A patch has been proposed to remove the -fcf-protection=full from the ebuild script:

https://bugs.gentoo.org/765442
Comment 12 H.J. Lu 2021-07-15 17:40:33 UTC
Fixed for GCC 11.
Comment 13 Martin Liška 2021-10-21 15:22:26 UTC
@H.J. Can you please document that one needs at least i686 CPU for the functionality?
Comment 14 H.J. Lu 2021-10-21 15:55:33 UTC
(In reply to Martin Liška from comment #13)
> @H.J. Can you please document that one needs at least i686 CPU for the
> functionality?

Like this?

diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index c66a25fcd69..71992b8c597 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -15542,7 +15542,8 @@ which functions and calls should be skipped from instrumentation
 (@pxref{Function Attributes}).
 
 Currently the x86 GNU/Linux target provides an implementation based
-on Intel Control-flow Enforcement Technology (CET).
+on Intel Control-flow Enforcement Technology (CET) which works for
+i686 processor or newer.
 
 @item -fstack-protector
 @opindex fstack-protector
Comment 15 Martin Liška 2021-10-21 16:14:29 UTC
(In reply to H.J. Lu from comment #14)
> (In reply to Martin Liška from comment #13)
> > @H.J. Can you please document that one needs at least i686 CPU for the
> > functionality?
> 
> Like this?
> 
> diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
> index c66a25fcd69..71992b8c597 100644
> --- a/gcc/doc/invoke.texi
> +++ b/gcc/doc/invoke.texi
> @@ -15542,7 +15542,8 @@ which functions and calls should be skipped from
> instrumentation
>  (@pxref{Function Attributes}).
>  
>  Currently the x86 GNU/Linux target provides an implementation based
> -on Intel Control-flow Enforcement Technology (CET).
> +on Intel Control-flow Enforcement Technology (CET) which works for
> +i686 processor or newer.
>  
>  @item -fstack-protector
>  @opindex fstack-protector

Yes, please.
Comment 16 GCC Commits 2021-10-21 19:09:46 UTC
The master branch has been updated by H.J. Lu <hjl@gcc.gnu.org>:

https://gcc.gnu.org/g:1373066a46d8d47abd97e46a005aef3b3dbfe94a

commit r12-4619-g1373066a46d8d47abd97e46a005aef3b3dbfe94a
Author: H.J. Lu <hjl.tools@gmail.com>
Date:   Thu Oct 21 09:45:14 2021 -0700

    x86: Document -fcf-protection requires i686 or newer
    
            PR target/98667
            * doc/invoke.texi: Document -fcf-protection requires i686 or
            new.
Comment 17 GCC Commits 2021-10-21 19:10:43 UTC
The releases/gcc-11 branch has been updated by H.J. Lu <hjl@gcc.gnu.org>:

https://gcc.gnu.org/g:e74336df42fa36244d576dd155d7e2e2c42bc3a0

commit r11-9179-ge74336df42fa36244d576dd155d7e2e2c42bc3a0
Author: H.J. Lu <hjl.tools@gmail.com>
Date:   Thu Oct 21 09:45:14 2021 -0700

    x86: Document -fcf-protection requires i686 or newer
    
            PR target/98667
            * doc/invoke.texi: Document -fcf-protection requires i686 or
            new.
    
    (cherry picked from commit 1373066a46d8d47abd97e46a005aef3b3dbfe94a)
Comment 18 GCC Commits 2021-10-21 19:11:27 UTC
The releases/gcc-10 branch has been updated by H.J. Lu <hjl@gcc.gnu.org>:

https://gcc.gnu.org/g:523dc71f5cb858da18e1f648269746dab519b445

commit r10-10228-g523dc71f5cb858da18e1f648269746dab519b445
Author: H.J. Lu <hjl.tools@gmail.com>
Date:   Thu Oct 21 09:45:14 2021 -0700

    x86: Document -fcf-protection requires i686 or newer
    
            PR target/98667
            * doc/invoke.texi: Document -fcf-protection requires i686 or
            new.
    
    (cherry picked from commit 1373066a46d8d47abd97e46a005aef3b3dbfe94a)
Comment 19 GCC Commits 2021-10-21 19:14:14 UTC
The releases/gcc-9 branch has been updated by H.J. Lu <hjl@gcc.gnu.org>:

https://gcc.gnu.org/g:5ed78f8bd84eb696579d928c816bc840664829b2

commit r9-9792-g5ed78f8bd84eb696579d928c816bc840664829b2
Author: H.J. Lu <hjl.tools@gmail.com>
Date:   Thu Oct 21 09:45:14 2021 -0700

    x86: Document -fcf-protection requires i686 or newer
    
            PR target/98667
            * doc/invoke.texi: Document -fcf-protection requires i686 or
            new.
    
    (cherry picked from commit 1373066a46d8d47abd97e46a005aef3b3dbfe94a)