golang/go

cmd/link: ELF `e_flags` does not contain `EF_ARM_VFP_FLOAT` on armv7l when statically linked

Open

#44,002 opened on Jan 30, 2021

View on GitHub
 (4 comments) (0 reactions) (0 assignees)Go (19,008 forks)batch import
NeedsInvestigationcompiler/runtimehelp wanted

Repository metrics

Stars
 (133,883 stars)
PR merge metrics
 (No merged PRs in 30d)

Description

What version of Go are you using (go version)?

Does this issue reproduce with the latest release?

Yes

What operating system and processor architecture are you using (go env)?

What did you do?

I have go code that involves vectorizeable floating point instructions. When compiling for armv7l, go correctly uses vector floating-point instructions, but does not mark the resultant executable as a 'hard float' executable:

import "fmt" import "math/rand"

func average(xs []float64) float64 { total := 0.0 for _, v := range xs { total += v } return total / float64(len(xs)) }

func main() { rand.Seed(0x6a756c6961) xs := make([]float64, 1000) for n := 0; n < 1000; n++ { xs[n] = rand.Float64() } fmt.Println("average: ", average(xs)) }

Compiling:

$ docker run -ti -v $(pwd):/app -w /app -e GOARCH=arm -e GOARM=7 golang go build -o float_abi float_abi.go

Inspecting ELF headers:

$ readelf -h ./float_abi
ELF Header:
  Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 
  Class:                             ELF32
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              EXEC (Executable file)
  Machine:                           ARM
  Version:                           0x1
  Entry point address:               0x6e800
  Start of program headers:          52 (bytes into file)
  Start of section headers:          276 (bytes into file)
  Flags:                             0x5000002, Version5 EABI, <unknown>
  Size of this header:               52 (bytes)
  Size of program headers:           32 (bytes)
  Number of program headers:         7
  Size of section headers:           40 (bytes)
  Number of section headers:         25
  Section header string table index: 3

Disassembly of average() showcasing vector instructions:

$ arm-linux-gnueabihf-objdump -d ./float_abi | grep 'main.average>:' -A 18
0009daf8 <main.average>:
   9daf8:       e59d0008        ldr     r0, [sp, #8]
   9dafc:       e59d1004        ldr     r1, [sp, #4]
   9db00:       e3a02000        mov     r2, #0
   9db04:       eeb70b00        vmov.f64        d0, #112        ; 0x3f800000  1.0
   9db08:       ee300b40        vsub.f64        d0, d0, d0
   9db0c:       ea000003        b       9db20 <main.average+0x28>
   9db10:       e0813182        add     r3, r1, r2, lsl #3
   9db14:       ed931b00        vldr    d1, [r3]
   9db18:       e2822001        add     r2, r2, #1
   9db1c:       ee300b01        vadd.f64        d0, d0, d1
   9db20:       e1520000        cmp     r2, r0
   9db24:       bafffff9        blt     9db10 <main.average+0x18>
   9db28:       ee0f0b10        vmov.32 d15[0], r0
   9db2c:       eeb81bcf        vcvt.f64.s32    d1, s30
   9db30:       ee800b01        vdiv.f64        d0, d0, d1
   9db34:       ed8d0b04        vstr    d0, [sp, #16]
   9db38:       e28ef000        add     pc, lr, #0

Note the vadd.f64 and the use of dX registers.

What did you expect to see?

I expect to see the Flags field above to have 0x400 set, marking this executable as using the "hard float" ABI. See the definitions in glibc which correspond to the values in the table on page 16 of this pdf.

What did you see instead?

Neither the hard nor soft float ABI flags are set, which I believe denotes that this program does not use any floating point arithmetic at all, which is clearly incorrect.

Contributor guide