-
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: support calls to SDYNIMPORT symbols on mips64 #46178
Comments
/cc @cherrymui |
Change https://golang.org/cl/320249 mentions this issue: |
I'd be surprised it use gp-relative addressing. I thought it does not use that mode by default? What happens if you pass
I'm not sure I followed this. What equivalent to what? Is this code generated by Go or by the C compiler/linker?
I agree this sounds like a good solution. But I don't think the code snippet has to be like that above. It is true that a call has to be made through R25. But the trampoline doesn't need to be exactly like that. It can use other instruction sequence and relocations to load the address to R25, without using the gp register. Another possibility is to always generate indirect calls through R25 on OpenBSD (possibly let the linker to rewrite to direct calls if the target is not DYNIMPORT). What we need then is to handle relocations for the address of a DYNIMPORT symbol. |
The use of
I'll try compiling some actual C code to see if this has any impact there. Also,
Apologies for not being clearer - this is basically the result of compiling an equivalent assembly call to a global symbol using clang, then disassembling the object file:
Good point - I guess the trampoline could use REGTMP in place of the GP register, however we would still need to load the same value that the linkers expected to be there, given that this is encoded into the final relocation, for example:
At least the original value would not have to be restored following the call.
I also considered that - given that we have a limited number of |
Compiling and disassembling some C code gives us a better insight/option:
This is generating code and relocations that acquires the general pointer value via relocations, rather than requiring it to be preserved, also meaning that we do not need to clobber the Go SB register. This does however rely on the function address being available (normally in register 25 aka |
Ugh, so this works, however the PIC library code we're calling into is expecting |
I meant to mention that I'm also wondering if we should not be saving/restoring (or reinitialising) the |
Change https://go.dev/cl/415815 mentions this issue: |
Change https://go.dev/cl/415816 mentions this issue: |
Add internal linking support for calling SDYNIMPORT symbols on mips64. This adds code to generate appropriate PLT and GOT entries, along with the various dynamic entries needed for the dynamic loader. Updates #36435, #46178 Change-Id: I783e0d028510ca2bca82bcbc745f2375770813fe Reviewed-on: https://go-review.googlesource.com/c/go/+/415815 Reviewed-by: Rong Zhang <rongrong@oss.cipunited.com> Run-TryBot: Ian Lance Taylor <iant@google.com> Run-TryBot: Joel Sing <joel@sing.id.au> Reviewed-by: Ian Lance Taylor <iant@google.com> Reviewed-by: Than McIntosh <thanm@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Auto-Submit: Ian Lance Taylor <iant@google.com>
The mips64 port currently fails to handle calls to
SDYNIMPORT
symbols, even when external linking is in use, since it emitsR_MIPS_26
relocations, resulting in "relocation truncated to fit" warnings. An equivalent call from assembly when compiled with LLVM results in the following:Furthermore, two relocations are produced for the external symbol - a
R_MIPS_CALL16
relocation for theld
instruction and aR_MIPS_JALR
relocation for thejalr
instruction.There are a couple of additional things to note here - firstly, PIC code requires that register 25 (
t9
) contains the address of the called function, which is why this register is used here. Secondly, when the external linker performs the R_MIPS_CALL16 relocation is is done with an expectedgp
register value, which is loaded by the dynamic linker. Unfortunately, Go currently uses this register and clobbers the value placed in it by the dynamic linker, breaking the relocation.This means there are effectively two things to solve:
Currently a
CALL
translates to a singleJAL
instruction with anR_CALLMIPS
(akaR_MIPS_26
) relocation - given that the assembler does not know if this is an internal function or anSDYNIMPORT
symbol, the easiest option is to likely produce trampolines for theSDYNIMPORT
calls, modelling the above assembly and generating the two matching relocations.In order for these relocations to work we likely have to avoid clobbering the
gp
register - one option may be to change Go'sREGSB
register (as was done fortp
onriscv64
). The other is to save the value of thegp
register at start up and restore thegp
value before calling anSDYNIMPORT
, switching it back to Go's value after the call returns.I've got a proof of concept working with external linking, trampoline generation and
gp
register save/restore onopenbsd/mips64
(I'll make this available soon) - in the mean time, I'm interested in feedback and/or other suggestions on these issues/approach, before I proceed further.The text was updated successfully, but these errors were encountered: