-
Notifications
You must be signed in to change notification settings - Fork 17.9k
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
cmd/link: unaligned loads generated for rodata on mips64 #42071
Comments
/cc @cherrymui |
https://tip.golang.org/src/cmd/internal/obj/objfile.go#L309 sets data symbol's alignment. Int64Sym is content-addressable, so it should have alignment set to 8.
I think it is quite rare for the toolchain to generate a negative offset. Maybe this offset is not calculated correctly. Do you know what symbol it is loading? Do you know its address, say, in gdb or using the nm command? |
Interesting... there goes that theory :)
The symbol is for the 1<<32 constant, which should be a symbol named In a different program (with imports), the same code disassembles to:
And the 0x100000000 value is correctly loaded from this address (into register a6):
The symbol name is not present in the symbol table in this case either, however it does exist just past the end of the named symbols in .rodata. |
It is a content-addressable symbol, so it will be dedup'd by content if there is another symbol with a different name but the same content. Some of those symbols are not in the symbol table, like gcbits, strings. In your first case (the one crashes), is the address in the RODATA section, just unaligned? Or it is completely off? |
Ah, interesting.
It appears to be
Which makes
So not only is it readable from gdb, but it also contains the value that is expected (1 << 32). I guess we're back to the original unaligned theory after all :) |
Okay, thanks. Do you know what is the symbol immediately before this address? (e.g. Also, is there a way I could build the binary myself? That would help me to find out why it is not aligned. Thanks. |
And that's confirmed by objdump:
I would expect that linux/mips64 would be the same, if you have access to such a system. Otherwise, this machine is running as the |
Change https://golang.org/cl/264897 mentions this issue: |
Thanks. |
Excellent, thanks! I'm currently rebuilding with that CL to confirm. |
I've confirmed that this does fix the issue - the code now disassembles to:
Where 0xa0000 - 24584 = 0x99ff8, which is obviously correctly aligned. The resulting binary now also runs correctly. |
The mips64 assembler deals with the load of constants that exceed 32 bits by placing them in rodata and loading from memory:
https://github.com/golang/go/blob/master/src/cmd/internal/obj/mips/obj0.go#L91
However, there does not appear to be any guarantee that the symbol added to rodata (via
ctxt.Int64Sym
) will have 64 bit alignment, even though the resulting code is anOn OpenBSD/octeon this results in the following:
The instruction triggering the SIGBUS is an
ld
of 0xa0000 - 25052 = 0x99e24.This presumably also happens on linux/mips64, however I would guess that the kernel deals with the unaligned access fault and performs multiple separate 32 bit loads (which will have a performance impact).
There are probably a few solutions, including laying out the RODATA section in descending symbol size order, or adding padding for alignment.
The text was updated successfully, but these errors were encountered: