diff options
| author | WANG Xuerui <git@xen0n.name> | 2025-10-06 18:09:14 +0800 |
|---|---|---|
| committer | abner chenc <chenguoqi@loongson.cn> | 2025-11-20 19:04:50 -0800 |
| commit | 4b0e3cc1d63a00ee184ea1f6b17e79808e3d9fdc (patch) | |
| tree | a39935c924fff622dc112d627030d86a5cc1fb1a /src/cmd/link | |
| parent | cdba82c7d6fce54b212872ae45d04c3911b11014 (diff) | |
| download | go-4b0e3cc1d63a00ee184ea1f6b17e79808e3d9fdc.tar.xz | |
cmd/link: support loading R_LARCH_PCREL20_S2 and R_LARCH_CALL36 relocs
Host libgcc.a (among other libraries) on loong64 systems may contain
such relocs if built with the "medium" code model and/or linker
relaxation, which is increasingly the case. Make the internal linker
aware of these for cgo interopability going forward.
While at it, fix some of the comments for the loong64-specific
RelocTypes.
Fixes #75562
Change-Id: I0810969dcd229c5131ef06b0f70f51d81a3be4cd
Reviewed-on: https://go-review.googlesource.com/c/go/+/709717
Reviewed-by: abner chenc <chenguoqi@loongson.cn>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Mark Freeman <markfreeman@google.com>
Reviewed-by: Meidan Li <limeidan@loongson.cn>
Reviewed-by: Junyang Shao <shaojunyang@google.com>
Diffstat (limited to 'src/cmd/link')
| -rw-r--r-- | src/cmd/link/internal/loadelf/ldelf.go | 6 | ||||
| -rw-r--r-- | src/cmd/link/internal/loong64/asm.go | 53 |
2 files changed, 48 insertions, 11 deletions
diff --git a/src/cmd/link/internal/loadelf/ldelf.go b/src/cmd/link/internal/loadelf/ldelf.go index 1c83f03a5d..8f4c1a5765 100644 --- a/src/cmd/link/internal/loadelf/ldelf.go +++ b/src/cmd/link/internal/loadelf/ldelf.go @@ -1065,13 +1065,15 @@ func relSize(arch *sys.Arch, pn string, elftype uint32) (uint8, uint8, error) { LOONG64 | uint32(elf.R_LARCH_PCALA_LO12)<<16, LOONG64 | uint32(elf.R_LARCH_GOT_PC_HI20)<<16, LOONG64 | uint32(elf.R_LARCH_GOT_PC_LO12)<<16, - LOONG64 | uint32(elf.R_LARCH_32_PCREL)<<16: + LOONG64 | uint32(elf.R_LARCH_32_PCREL)<<16, + LOONG64 | uint32(elf.R_LARCH_PCREL20_S2)<<16: return 4, 4, nil case LOONG64 | uint32(elf.R_LARCH_64)<<16, LOONG64 | uint32(elf.R_LARCH_ADD64)<<16, LOONG64 | uint32(elf.R_LARCH_SUB64)<<16, - LOONG64 | uint32(elf.R_LARCH_64_PCREL)<<16: + LOONG64 | uint32(elf.R_LARCH_64_PCREL)<<16, + LOONG64 | uint32(elf.R_LARCH_CALL36)<<16: return 8, 8, nil case S390X | uint32(elf.R_390_8)<<16: diff --git a/src/cmd/link/internal/loong64/asm.go b/src/cmd/link/internal/loong64/asm.go index e7f3fd1d98..219cfc7196 100644 --- a/src/cmd/link/internal/loong64/asm.go +++ b/src/cmd/link/internal/loong64/asm.go @@ -85,7 +85,8 @@ func adddynrel(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loade } return true - case objabi.ElfRelocOffset + objabi.RelocType(elf.R_LARCH_B26): + case objabi.ElfRelocOffset + objabi.RelocType(elf.R_LARCH_B26), + objabi.ElfRelocOffset + objabi.RelocType(elf.R_LARCH_CALL36): if targType == sym.SDYNIMPORT { addpltsym(target, ldr, syms, targ) su := ldr.MakeSymbolUpdater(s) @@ -95,8 +96,12 @@ func adddynrel(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loade if targType == 0 || targType == sym.SXREF { ldr.Errorf(s, "unknown symbol %s in callloong64", ldr.SymName(targ)) } + relocType := objabi.R_CALLLOONG64 + if r.Type() == objabi.ElfRelocOffset+objabi.RelocType(elf.R_LARCH_CALL36) { + relocType = objabi.R_LOONG64_CALL36 + } su := ldr.MakeSymbolUpdater(s) - su.SetRelocType(rIdx, objabi.R_CALLLOONG64) + su.SetRelocType(rIdx, relocType) return true case objabi.ElfRelocOffset + objabi.RelocType(elf.R_LARCH_GOT_PC_HI20), @@ -117,7 +122,8 @@ func adddynrel(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loade return true case objabi.ElfRelocOffset + objabi.RelocType(elf.R_LARCH_PCALA_HI20), - objabi.ElfRelocOffset + objabi.RelocType(elf.R_LARCH_PCALA_LO12): + objabi.ElfRelocOffset + objabi.RelocType(elf.R_LARCH_PCALA_LO12), + objabi.ElfRelocOffset + objabi.RelocType(elf.R_LARCH_PCREL20_S2): if targType == sym.SDYNIMPORT { ldr.Errorf(s, "unexpected relocation for dynamic symbol %s", ldr.SymName(targ)) } @@ -125,12 +131,17 @@ func adddynrel(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loade ldr.Errorf(s, "unknown symbol %s", ldr.SymName(targ)) } - su := ldr.MakeSymbolUpdater(s) - if r.Type() == objabi.ElfRelocOffset+objabi.RelocType(elf.R_LARCH_PCALA_HI20) { - su.SetRelocType(rIdx, objabi.R_LOONG64_ADDR_HI) - } else { - su.SetRelocType(rIdx, objabi.R_LOONG64_ADDR_LO) + var relocType objabi.RelocType + switch r.Type() - objabi.ElfRelocOffset { + case objabi.RelocType(elf.R_LARCH_PCALA_HI20): + relocType = objabi.R_LOONG64_ADDR_HI + case objabi.RelocType(elf.R_LARCH_PCALA_LO12): + relocType = objabi.R_LOONG64_ADDR_LO + case objabi.RelocType(elf.R_LARCH_PCREL20_S2): + relocType = objabi.R_LOONG64_ADDR_PCREL20_S2 } + su := ldr.MakeSymbolUpdater(s) + su.SetRelocType(rIdx, relocType) return true case objabi.ElfRelocOffset + objabi.RelocType(elf.R_LARCH_ADD64), @@ -418,6 +429,11 @@ func elfreloc1(ctxt *ld.Link, out *ld.OutBuf, ldr *loader.Loader, s loader.Sym, out.Write64(uint64(elf.R_LARCH_B26) | uint64(elfsym)<<32) out.Write64(uint64(r.Xadd)) + case objabi.R_LOONG64_CALL36: + out.Write64(uint64(sectoff)) + out.Write64(uint64(elf.R_LARCH_CALL36) | uint64(elfsym)<<32) + out.Write64(uint64(r.Xadd)) + case objabi.R_LOONG64_TLS_IE_HI: out.Write64(uint64(sectoff)) out.Write64(uint64(elf.R_LARCH_TLS_IE_PC_HI20) | uint64(elfsym)<<32) @@ -438,6 +454,11 @@ func elfreloc1(ctxt *ld.Link, out *ld.OutBuf, ldr *loader.Loader, s loader.Sym, out.Write64(uint64(elf.R_LARCH_PCALA_HI20) | uint64(elfsym)<<32) out.Write64(uint64(r.Xadd)) + case objabi.R_LOONG64_ADDR_PCREL20_S2: + out.Write64(uint64(sectoff)) + out.Write64(uint64(elf.R_LARCH_PCREL20_S2) | uint64(elfsym)<<32) + out.Write64(uint64(r.Xadd)) + case objabi.R_LOONG64_GOT_HI: out.Write64(uint64(sectoff)) out.Write64(uint64(elf.R_LARCH_GOT_PC_HI20) | uint64(elfsym)<<32) @@ -463,7 +484,8 @@ func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loade default: return val, 0, false case objabi.R_LOONG64_ADDR_HI, - objabi.R_LOONG64_ADDR_LO: + objabi.R_LOONG64_ADDR_LO, + objabi.R_LOONG64_ADDR_PCREL20_S2: // set up addend for eventual relocation via outer symbol. rs, _ := ld.FoldSubSymbolOffset(ldr, rs) rst := ldr.SymType(rs) @@ -474,6 +496,7 @@ func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loade case objabi.R_LOONG64_TLS_LE_HI, objabi.R_LOONG64_TLS_LE_LO, objabi.R_CALLLOONG64, + objabi.R_LOONG64_CALL36, objabi.R_JMPLOONG64, objabi.R_LOONG64_TLS_IE_HI, objabi.R_LOONG64_TLS_IE_LO, @@ -499,6 +522,10 @@ func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loade return val&0xffc003ff | (t << 10), noExtReloc, isOk } return val&0xfe00001f | (t << 5), noExtReloc, isOk + case objabi.R_LOONG64_ADDR_PCREL20_S2: + pc := ldr.SymValue(s) + int64(r.Off()) + t := (ldr.SymAddr(rs) + r.Add() - pc) >> 2 + return val&0xfe00001f | ((t & 0xfffff) << 5), noExtReloc, isOk case objabi.R_LOONG64_TLS_LE_HI, objabi.R_LOONG64_TLS_LE_LO: t := ldr.SymAddr(rs) + r.Add() @@ -512,6 +539,14 @@ func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loade t := ldr.SymAddr(rs) + r.Add() - pc return val&0xfc000000 | (((t >> 2) & 0xffff) << 10) | (((t >> 2) & 0x3ff0000) >> 16), noExtReloc, isOk + case objabi.R_LOONG64_CALL36: + pc := ldr.SymValue(s) + int64(r.Off()) + t := (ldr.SymAddr(rs) + r.Add() - pc) >> 2 + // val is pcaddu18i (lower half) + jirl (upper half) + pcaddu18i := (val & 0xfe00001f) | (((t + 0x8000) >> 16) << 5) + jirl := ((val >> 32) & 0xfc0003ff) | ((t & 0xffff) << 10) + return pcaddu18i | (jirl << 32), noExtReloc, isOk + case objabi.R_JMP16LOONG64, objabi.R_JMP21LOONG64: pc := ldr.SymValue(s) + int64(r.Off()) |
