Skip to content

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

Open
@staticfloat

Description

@staticfloat

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

go version go1.15.7 linux/amd64

Does this issue reproduce with the latest release?

Yes

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

go env Output
go env
GO111MODULE=""
GOARCH="arm"
GOBIN=""
GOCACHE="/root/.cache/go-build"
GOENV="/root/.config/go/env"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOINSECURE=""
GOMODCACHE="/go/pkg/mod"
GONOPROXY=""
GONOSUMDB=""
GOOS="linux"
GOPATH="/go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/usr/local/go"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/usr/local/go/pkg/tool/linux_amd64"
GCCGO="gccgo"
GOARM="7"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="0"
GOMOD=""
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -marm -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build305676071=/tmp/go-build -gno-record-gcc-switches"

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:

float_abi.go source
package main

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    NeedsInvestigationSomeone must examine and confirm this is a valid issue and not a duplicate of an existing one.compiler/runtimeIssues related to the Go compiler and/or runtime.help wanted

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions