New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
encoding/binary: add var NativeEndian; also x/sys/cpu.IsBigEndian #57237
Comments
Yes please. Another option: unsafe.NativeEndian to imply that you shouldn't use this unless you are aware of the implications? |
CC @robpike |
FWIW, I know the author of that package, and he’s amenable to adding a constant. But an x/sys/cpu or build tag option would be better. :) |
See josharian/native#3 Updates golang/go#57237 Change-Id: I238c04c6654e5b9e7d9cfb81a7bbc5e1043a84a2 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
Fixes u-root#7 Updates golang/go#57237 Signed-off-by: Brad Fitzpatrick <brad@danga.com>
See josharian/native#3 Updates golang/go#57237 Change-Id: I238c04c6654e5b9e7d9cfb81a7bbc5e1043a84a2 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
Fixes #7 Updates golang/go#57237 Signed-off-by: Brad Fitzpatrick <brad@danga.com>
You know my position about byte order. Yes, it's sometimes necessary but it's used far more than it should be. I'd prefer to take up @josharian's first suggestion and not have the standard library promote the concept. |
To pick up this change: u-root/uio@c353755 Updates golang/go#57237
To pick up this change: u-root/uio@c353755 Updates golang/go#57237 Signed-off-by: Brad Fitzpatrick <brad@danga.com>
What about |
I'm not going to die on this hill, but know too that big/little endian is not the full story for some architectures. Maybe Go will never support a nutty layout, but who knows? In other words, is a boolean sufficient? It might be nowadays, but I honestly don't know. It's probably sufficient to support the architectures encoding/binary does, so maybe it's enough. At least your suggestion doesn't promote the idea of "native" byte order explicitly. But: A single third-party package that just told you the byte order by computing it (this can only be done unsafely, which is a BIG part of why I dislike the concept) seems like the real right answer to me. |
Is part of the problem here more one of naming, e.g. "NativeEndian", perhaps something closer to what this is used for in most good cases is the systems ABI endianness. I'm not sure of a good short name to describe that, but perhaps if we had one it would be less objectionable? |
@raggi Not especially. It's not what it's called, it's what it represents, an internal detail that is almost always (not always, but almost always) irrelevant. A long history of bad C code has taught people that it matters more than it does. Only unsafe code can care. |
I made this exact mistake recently. I'm working on a pure Go Wayland protocol implementation. Wayland, despite being essentially a network protocol, is constrained to Unix domain sockets for various practical reasons. Since everything's on the same machine anyways, I assume, the developers decided to just use native endianness for data being sent. Early on in my project, I created a global I have to agree with @robpike. I used to wonder why this was missing but now I just don't see the point. All it would do would be to obscure stuff that probably should be Unless I'm missing something, none of these seem like they actually require any kind of Endianness is generally not something that should affect anything outside of network protocols and file formats. In other words, it only really matters for stuff where data could be read by two processes that might be running on different computers. In those cases, the endianness needs to be explicitly declared as something standardized between the two, hence |
You have to be careful with alignment on some archs with that sort of unsafe cast. Typically what I've done in C is memcpy to the destination and let gcc figure out whether that has to be byte by byte or can be word-wise, with load store folding removing the insufficiency. |
How so, and how does a v.hdrLen = endian.Native.Uint16(b[2:]) and v.hdrLen = *(*uint16)(unsafe.Pointer(&b[2])) Genuinely curious. It's reading the same bytes in the same order. If there are issues with reading those bytes that seems like it should be something the compiler should handle transparently. |
@DeedleFake the compiler only coalesces byte-by-byte memory reads/writes if it knows that it is safe to do so, based on the architecture, alignment, whatnot. The unsafe version says to the compiler: just do it, whether or not it is safe. |
What actually happens if you attempt to do v.hdrLen = *(*uint16)(unsafe.Pointer(&b[2])) on something like MIPS and the alignment isn't correct? Do you just get junk data? Does it panic? That's not something I've run into before, despite working with some relatively low level stuff on MIPS a bit a fair while back. Edit: Never mind. I think I answered my own question. |
if we have known endian at compile time, If could be some problem when cross compile. For example, the host machine is
now this code have been generate(or somehow) to encoding/binary, it's ok if the target host is GOARCH=arm64. what if now we need to cross compile a program to a big endian machine like arm64be, this may cause problem. the native endian become littleEndian which should be bigEndian. |
@cuiweixie There isn't going to be any generated code here. We will use build tags to select which variant of |
Wow, it's a good idea. Is it someone working on this. If not, maybe I can try to implement proposal. |
Change https://go.dev/cl/463335 mentions this issue: |
Why do you need a special function IsBigEndian? You could just ask if |
Part of this proposal is to add a new constant (not function) |
Change https://go.dev/cl/463218 mentions this issue: |
Copy the definition of x/sys/unix.isBigEndian to x/sys/cpu. Updates golang/go#57237 Change-Id: Iefbf4303720445611de93b0a3ea365f8208c033b Reviewed-on: https://go-review.googlesource.com/c/sys/+/463335 Reviewed-by: Ian Lance Taylor <iant@google.com> Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org> Run-TryBot: Tobias Klauser <tobias.klauser@gmail.com> Reviewed-by: Dmitri Shuralyov <dmitshur@google.com> Reviewed-by: Rob Pike <r@golang.org> TryBot-Result: Gopher Robot <gobot@golang.org>
Updates #57237 Change-Id: I149c8b7eeac91b87b5810250f96d48ca87135807 Reviewed-on: https://go-review.googlesource.com/c/go/+/463218 Reviewed-by: Ian Lance Taylor <iant@google.com> Reviewed-by: Dmitri Shuralyov <dmitshur@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Run-TryBot: Ian Lance Taylor <iant@google.com> Run-TryBot: xie cui <523516579@qq.com> Auto-Submit: Ian Lance Taylor <iant@google.com>
Change https://go.dev/cl/463985 mentions this issue: |
No longer needed. Native byte order is not often needed, but will eventually show up in standard library anyway (golang/go#57237).
Updates #57237 Change-Id: Ib626610130cae9c1d1aff5dd2a5035ffde0e127f Reviewed-on: https://go-review.googlesource.com/c/go/+/463985 Reviewed-by: Ian Lance Taylor <iant@google.com> Run-TryBot: xie cui <523516579@qq.com> TryBot-Result: Gopher Robot <gobot@golang.org> Run-TryBot: Ian Lance Taylor <iant@google.com> Auto-Submit: Ian Lance Taylor <iant@google.com> Reviewed-by: Michael Knyszek <mknyszek@google.com>
See golang/go#57237 for history.
See golang/go#57237 Change-Id: If47ab6de7c1610998a5808e945c4177c561eab45 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
See golang/go#57237 for history.
See golang/go#57237 Change-Id: If47ab6de7c1610998a5808e945c4177c561eab45 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
See golang/go#57237 Change-Id: If47ab6de7c1610998a5808e945c4177c561eab45 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
See golang/go#57237 Change-Id: If47ab6de7c1610998a5808e945c4177c561eab45 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
See josharian/native#3 Updates golang/go#57237 Change-Id: I238c04c6654e5b9e7d9cfb81a7bbc5e1043a84a2 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
To pull in insomniacslk/dhcp#484 to pull in u-root/uio#8 Updates golang/go#57237 Change-Id: I1e56656e0dc9ec0b870f799fe3bc18b3caac1ee4 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
See golang/go#57237 Change-Id: If47ab6de7c1610998a5808e945c4177c561eab45 Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
No longer needed. Native byte order is not often needed, but will eventually show up in standard library anyway (golang/go#57237).
The pkg/private/common, util and xtest packages have rather fuzzy scope, and have accumulated a bit of cruft and unused or outdated functionality. Clean this up a bit: * pkg/private/common: * remove unused constants * remove outdated error handling helpers and replace remaining use * remove NativeOrder and IsBigEndian: No longer needed. Native byte order is not often needed, but will eventually show up in standard library anyway (golang/go#57237). * pkg/private/util: * remove unused helper functionality * remove Checksum: only used to compute reference value in slayers test cases. Use a simpler, non-optimized implementation for this. Closes #4262. * move RunsInDocker to private/env * move ASList to tools/integration * pkg/private/xtest: * remove unused helpers * remove unused Callback and MockCallback * replace FailOnErr with require.NoError * replace AssertErrorsIs with assert.ErrorIs There are still more things to clean up in `pkg/private`, in future PRs, in particular: * `common.ErrMsg` should be integrated in `serrors` * `common.IFIDType` should be removed or renamed and moved somewhere more appropriate * Merge the remainder of `util` and `common` * Clean up `LinkType` and `RevInfo` from `pkg/private/ctrl`
Updates golang#57237 Change-Id: Ib626610130cae9c1d1aff5dd2a5035ffde0e127f Reviewed-on: https://go-review.googlesource.com/c/go/+/463985 Reviewed-by: Ian Lance Taylor <iant@google.com> Run-TryBot: xie cui <523516579@qq.com> TryBot-Result: Gopher Robot <gobot@golang.org> Run-TryBot: Ian Lance Taylor <iant@google.com> Auto-Submit: Ian Lance Taylor <iant@google.com> Reviewed-by: Michael Knyszek <mknyszek@google.com>
I'd like to revisit #35398 (proposal: encoding/binary: add NativeEndian). Sorry. I know the history & people's opinions already. But I come with a story!😄
Go 1.19 added support for
GOARCH=loong64
(https://go.dev/doc/go1.19#loong64)So naturally somebody wanted to compile
tailscale.com/cmd/tailscaled
withGOOS=linux GOARCH=loong64
. Compilation failed.It turned out we have four different native endian packages in our dependency tree:
const Big = false
,var Native = binary.LittleEndian
)var Endian = binary.LittleEndian
)"tailscale.com/net/interfaces" => "github.com/mdlayher/netlink" => "github.com/mdlayher/netlink/nlenc" "github.com/josharian/native"
var NativeEndian = binary.LittleEndian
)"tailscale.com/wgengine/router" => "tailscale.com/net/dns" => "tailscale.com/net/tstun" => "github.com/insomniacslk/dhcp/dhcpv4" => "github.com/u-root/uio/uio" => "github.com/u-root/uio/ubinary"
wireguard/endian
(in review at https://github.com/WireGuard/wireguard-go/pull/64/files#diff-8b7f475f3cbc65d1d51dd1c959d0232aad2aed0fbf7967207a97bfb0f94abdba) because it doesn't take external dependencies outside ofstd
orgolang.org/x/*
So we had to update all four, along with the various requisite go.mod bumps.
Some observations:
github.com/josharian/native
that he mentioned in proposal: encoding/binary: add NativeEndian #35398 (comment) is closest, but lacks the constant that we ended up needing in Tailscale. So everybody makes their own local copies instead. That works until a new GOARCH comes along. Maybe that's rare enough? But I'm sure moreriscv*
variants will come along at some point.x/sys/cpu already has this code:
https://cs.opensource.google/go/x/sys/+/refs/tags/v0.3.0:cpu/byteorder.go;l=44
And it has even more GOARCH values (for gccgo) than any other package has!
So everybody has a different subset of GOARCH values it seems.
I know people don't want to encourage thinking about or abusing endianness, but it's a reality when talking to kernel APIs. And this is kinda ridiculous, having this duplicated incompletely everywhere.
It would've been neat if Go could've added
loong64
and had a bunch of code in the Go ecosystem just work right away and not require adjusting build tags.Alternatively, if
std
andx/sys/cpu
are too objectionable: what about new build tags?/cc @josharian @mdlayher @hugelgupf @zx2c4 @yetist @jwhited @raggi
The text was updated successfully, but these errors were encountered: