-
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: do not reject addresses >= 2³¹ #7980
Labels
Milestone
Comments
All that's needed is to prevent the linker from stripping any of the arrays, so this suffices: func main() { _, _, _ = a[0], b[0], c[0] } Looks like a 32 bit overflow in the linker somewhere. Disassembly of main, array size 1 << 26: 0x0000000000002000 <+0>: mov 0x20075cc0,%rdx 0x0000000000002008 <+8>: mov 0x40075cc0,%rcx 0x0000000000002010 <+16>: mov 0x75cc0,%rbx 0x0000000000002018 <+24>: retq Disassembly of main, array size 1 << 27: 0x0000000000002000 <+0>: mov 0x40075cc0,%rdx 0x0000000000002008 <+8>: mov 0xffffffff80075cc0,%rcx 0x0000000000002010 <+16>: mov 0x75cc0,%rbx 0x0000000000002018 <+24>: retq |
Scratch the overflow comment. It appears that the 32 bit operand to MOV gets sign-extended by the processor. Note that the machine code does not contain 0xffffffff: 0x0000000000002000 <+0>: 48 8b 14 25 c0 5c 07 40 mov 0x40075cc0,%rdx 0x0000000000002008 <+8>: 48 8b 0c 25 c0 5c 07 80 mov 0xffffffff80075cc0,%rcx 0x0000000000002010 <+16>: 48 8b 1c 25 c0 5c 07 00 mov 0x75cc0,%rbx gdb disassembler's sign extension matches observed behavior--the panic is due to an attempt to dereference 0xffffffff80075cc0. It also matches http://onlinedisassembler.com/odaweb/iH4HYC/0. The two disassemblers I tried that do symbol resolution (Hopper.app and rsc's new x86 disassembler) incorrectly resolve this address to the main.c symbol. I think that we need to do relative addressing for addresses above 2**31. This might be a biggish change. It's also worth noting that this bug is not new -- it reproduces with Go 1.2. I'm going to stop working on this for now; my head hurts from wading through Intel's docs. |
for amd64, offsets are always signed, and also only 32-bit offset is offered. so to access address larger than 2^31-1, we need to first do a 64-bit literal load into a register and then indirectly load from that register. this might not be the only issue when the linker cannot handle 2GB+ data, so i think that we can defer it to 1.4. (although it's easy to fix this particular problem in liblink.) |
CL https://golang.org/cl/91500046 mentions this issue. |
Owner changed to @minux. Status changed to Started. |
This issue was updated by revision 6612983. This CL make the linker abort for the example program. For Go 1.4, we need to find a general way to handle large memory model programs. LGTM=dave, josharian, iant R=iant, dave, josharian CC=golang-codereviews https://golang.org/cl/91500046 Committer: Russ Cox |
Tangentially, rejecting 32-bit addresses >=2**31 means 6l can't link programs using the x86-64 kernel code model. Under that model, the program is loaded into the top 2GB of memory, so sign extending addresses is okay/desirable. I prepared a CL (https://golang.org/cl/117800044/) to change the "(int32)o < 0" check with "o != (int32)o", and also to change INITTEXT and INITDAT from int64 to uint64 (otherwise strtoll() caps the flags to LONG_MAX, and you can't specify an appropriate text address). With that CL, I'm able to successfully link a Go hello-world program using -ldflags='-T 0xffffffff80000c00', and it looks right if I inspect it with readelf. Of course, the Go runtime doesn't support running as a kernel, and no supported Go OS allows running userspace applications in this code model either, so it's perhaps moot. |
I think we basically decided this was okay. |
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
The text was updated successfully, but these errors were encountered: