cpu: fix auxval parsing on big-endian systems
The words in auxval are encoded in native byte order.
I haven't added a test. This fix will be tested when s390x support
is added to the package.
Change-Id: I276f833660e6906c319995798faf9054ffc69461
Reviewed-on: https://go-review.googlesource.com/c/162902
Run-TryBot: Michael Munday <mike.munday@ibm.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Tobias Klauser <tobias.klauser@gmail.com>
diff --git a/cpu/byteorder.go b/cpu/byteorder.go
new file mode 100644
index 0000000..da6b9e4
--- /dev/null
+++ b/cpu/byteorder.go
@@ -0,0 +1,30 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package cpu
+
+import (
+ "encoding/binary"
+ "runtime"
+)
+
+// hostByteOrder returns binary.LittleEndian on little-endian machines and
+// binary.BigEndian on big-endian machines.
+func hostByteOrder() binary.ByteOrder {
+ switch runtime.GOARCH {
+ case "386", "amd64", "amd64p32",
+ "arm", "arm64",
+ "mipsle", "mips64le", "mips64p32le",
+ "ppc64le",
+ "riscv", "riscv64":
+ return binary.LittleEndian
+ case "armbe", "arm64be",
+ "mips", "mips64", "mips64p32",
+ "ppc", "ppc64",
+ "s390", "s390x",
+ "sparc", "sparc64":
+ return binary.BigEndian
+ }
+ panic("unknown architecture")
+}
diff --git a/cpu/cpu_linux.go b/cpu/cpu_linux.go
index a8452e0..5ed6964 100644
--- a/cpu/cpu_linux.go
+++ b/cpu/cpu_linux.go
@@ -7,9 +7,7 @@
package cpu
import (
- "encoding/binary"
"io/ioutil"
- "runtime"
)
const (
@@ -18,7 +16,7 @@
procAuxv = "/proc/self/auxv"
- uintSize uint = 32 << (^uint(0) >> 63)
+ uintSize = int(32 << (^uint(0) >> 63))
)
// For those platforms don't have a 'cpuid' equivalent we use HWCAP/HWCAP2
@@ -33,22 +31,18 @@
panic("read proc auxv failed: " + err.Error())
}
- pb := int(uintSize / 8)
-
- for i := 0; i < len(buf)-pb*2; i += pb * 2 {
+ bo := hostByteOrder()
+ for len(buf) >= 2*(uintSize/8) {
var tag, val uint
switch uintSize {
case 32:
- tag = uint(binary.LittleEndian.Uint32(buf[i:]))
- val = uint(binary.LittleEndian.Uint32(buf[i+pb:]))
+ tag = uint(bo.Uint32(buf[0:]))
+ val = uint(bo.Uint32(buf[4:]))
+ buf = buf[8:]
case 64:
- if runtime.GOARCH == "ppc64" {
- tag = uint(binary.BigEndian.Uint64(buf[i:]))
- val = uint(binary.BigEndian.Uint64(buf[i+pb:]))
- } else {
- tag = uint(binary.LittleEndian.Uint64(buf[i:]))
- val = uint(binary.LittleEndian.Uint64(buf[i+pb:]))
- }
+ tag = uint(bo.Uint64(buf[0:]))
+ val = uint(bo.Uint64(buf[8:]))
+ buf = buf[16:]
}
switch tag {
case _AT_HWCAP: