Skip to content

Commit 4b0e3cc

Browse files
xen0nabner-chenc
authored andcommitted
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 <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]> Reviewed-by: Mark Freeman <[email protected]> Reviewed-by: Meidan Li <[email protected]> Reviewed-by: Junyang Shao <[email protected]>
1 parent cdba82c commit 4b0e3cc

File tree

5 files changed

+96
-44
lines changed

5 files changed

+96
-44
lines changed

src/cmd/internal/obj/fips140.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -354,8 +354,10 @@ func (s *LSym) checkFIPSReloc(ctxt *Link, rel Reloc) {
354354
objabi.R_CALLLOONG64,
355355
objabi.R_CALLPOWER,
356356
objabi.R_GOTPCREL,
357-
objabi.R_LOONG64_ADDR_LO, // used with PC-relative load
358-
objabi.R_LOONG64_ADDR_HI, // used with PC-relative load
357+
objabi.R_LOONG64_ADDR_LO, // used with PC-relative load
358+
objabi.R_LOONG64_ADDR_HI, // used with PC-relative load
359+
objabi.R_LOONG64_ADDR_PCREL20_S2, // used with PC-relative load
360+
objabi.R_LOONG64_CALL36,
359361
objabi.R_LOONG64_TLS_LE_HI,
360362
objabi.R_LOONG64_TLS_LE_LO,
361363
objabi.R_LOONG64_TLS_IE_HI,

src/cmd/internal/objabi/reloctype.go

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -334,17 +334,25 @@ const (
334334
R_LOONG64_ADDR_HI
335335
R_LOONG64_ADDR_LO
336336

337+
// R_LOONG64_ADDR_PCREL20_S2 resolves to the 22-bit, 4-byte aligned offset of an
338+
// external address, by encoding it into a PCADDI instruction.
339+
R_LOONG64_ADDR_PCREL20_S2
340+
337341
// R_LOONG64_TLS_LE_HI resolves to the high 20 bits of a TLS address (offset from
338342
// thread pointer), by encoding it into the instruction.
339343
// R_LOONG64_TLS_LE_LO resolves to the low 12 bits of a TLS address (offset from
340344
// thread pointer), by encoding it into the instruction.
341345
R_LOONG64_TLS_LE_HI
342346
R_LOONG64_TLS_LE_LO
343347

344-
// R_CALLLOONG64 resolves to non-PC-relative target address of a CALL (BL/JIRL)
345-
// instruction, by encoding the address into the instruction.
348+
// R_CALLLOONG64 resolves to the 28-bit 4-byte aligned PC-relative target
349+
// address of a BL instruction, by encoding it into the instruction.
346350
R_CALLLOONG64
347351

352+
// R_LOONG64_CALL36 resolves to the 38-bit 4-byte aligned PC-relative target
353+
// address of a PCADDU18I + JIRL pair, by encoding it into the instructions.
354+
R_LOONG64_CALL36
355+
348356
// R_LOONG64_TLS_IE_HI and R_LOONG64_TLS_IE_LO relocates a pcalau12i, ld.d
349357
// pair to compute the address of the GOT slot of the tls symbol.
350358
R_LOONG64_TLS_IE_HI
@@ -360,14 +368,17 @@ const (
360368
// 64-bit in-place subtraction.
361369
R_LOONG64_SUB64
362370

363-
// R_JMP16LOONG64 resolves to 18-bit PC-relative target address of a JMP instructions.
371+
// R_JMP16LOONG64 resolves to the 18-bit 4-byte aligned PC-relative target
372+
// address of a BEQ/BNE/BLT/BGE/BLTU/BGEU instruction, by encoding it into
373+
// the instruction.
364374
R_JMP16LOONG64
365375

366-
// R_JMP21LOONG64 resolves to 23-bit PC-relative target address of a JMP instructions.
376+
// R_JMP21LOONG64 resolves to the 23-bit 4-byte aligned PC-relative target
377+
// address of a BEQZ/BNEZ instruction, by encoding it into the instruction.
367378
R_JMP21LOONG64
368379

369-
// R_JMPLOONG64 resolves to non-PC-relative target address of a JMP instruction,
370-
// by encoding the address into the instruction.
380+
// R_JMPLOONG64 resolves to the 28-bit 4-byte aligned PC-relative target
381+
// address of a B instruction, by encoding it into the instruction.
371382
R_JMPLOONG64
372383

373384
// R_ADDRMIPSU (only used on mips/mips64) resolves to the sign-adjusted "upper" 16

src/cmd/internal/objabi/reloctype_string.go

Lines changed: 27 additions & 25 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/cmd/link/internal/loadelf/ldelf.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1065,13 +1065,15 @@ func relSize(arch *sys.Arch, pn string, elftype uint32) (uint8, uint8, error) {
10651065
LOONG64 | uint32(elf.R_LARCH_PCALA_LO12)<<16,
10661066
LOONG64 | uint32(elf.R_LARCH_GOT_PC_HI20)<<16,
10671067
LOONG64 | uint32(elf.R_LARCH_GOT_PC_LO12)<<16,
1068-
LOONG64 | uint32(elf.R_LARCH_32_PCREL)<<16:
1068+
LOONG64 | uint32(elf.R_LARCH_32_PCREL)<<16,
1069+
LOONG64 | uint32(elf.R_LARCH_PCREL20_S2)<<16:
10691070
return 4, 4, nil
10701071

10711072
case LOONG64 | uint32(elf.R_LARCH_64)<<16,
10721073
LOONG64 | uint32(elf.R_LARCH_ADD64)<<16,
10731074
LOONG64 | uint32(elf.R_LARCH_SUB64)<<16,
1074-
LOONG64 | uint32(elf.R_LARCH_64_PCREL)<<16:
1075+
LOONG64 | uint32(elf.R_LARCH_64_PCREL)<<16,
1076+
LOONG64 | uint32(elf.R_LARCH_CALL36)<<16:
10751077
return 8, 8, nil
10761078

10771079
case S390X | uint32(elf.R_390_8)<<16:

src/cmd/link/internal/loong64/asm.go

Lines changed: 44 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,8 @@ func adddynrel(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loade
8585
}
8686
return true
8787

88-
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_LARCH_B26):
88+
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_LARCH_B26),
89+
objabi.ElfRelocOffset + objabi.RelocType(elf.R_LARCH_CALL36):
8990
if targType == sym.SDYNIMPORT {
9091
addpltsym(target, ldr, syms, targ)
9192
su := ldr.MakeSymbolUpdater(s)
@@ -95,8 +96,12 @@ func adddynrel(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loade
9596
if targType == 0 || targType == sym.SXREF {
9697
ldr.Errorf(s, "unknown symbol %s in callloong64", ldr.SymName(targ))
9798
}
99+
relocType := objabi.R_CALLLOONG64
100+
if r.Type() == objabi.ElfRelocOffset+objabi.RelocType(elf.R_LARCH_CALL36) {
101+
relocType = objabi.R_LOONG64_CALL36
102+
}
98103
su := ldr.MakeSymbolUpdater(s)
99-
su.SetRelocType(rIdx, objabi.R_CALLLOONG64)
104+
su.SetRelocType(rIdx, relocType)
100105
return true
101106

102107
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_LARCH_GOT_PC_HI20),
@@ -117,20 +122,26 @@ func adddynrel(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loade
117122
return true
118123

119124
case objabi.ElfRelocOffset + objabi.RelocType(elf.R_LARCH_PCALA_HI20),
120-
objabi.ElfRelocOffset + objabi.RelocType(elf.R_LARCH_PCALA_LO12):
125+
objabi.ElfRelocOffset + objabi.RelocType(elf.R_LARCH_PCALA_LO12),
126+
objabi.ElfRelocOffset + objabi.RelocType(elf.R_LARCH_PCREL20_S2):
121127
if targType == sym.SDYNIMPORT {
122128
ldr.Errorf(s, "unexpected relocation for dynamic symbol %s", ldr.SymName(targ))
123129
}
124130
if targType == 0 || targType == sym.SXREF {
125131
ldr.Errorf(s, "unknown symbol %s", ldr.SymName(targ))
126132
}
127133

128-
su := ldr.MakeSymbolUpdater(s)
129-
if r.Type() == objabi.ElfRelocOffset+objabi.RelocType(elf.R_LARCH_PCALA_HI20) {
130-
su.SetRelocType(rIdx, objabi.R_LOONG64_ADDR_HI)
131-
} else {
132-
su.SetRelocType(rIdx, objabi.R_LOONG64_ADDR_LO)
134+
var relocType objabi.RelocType
135+
switch r.Type() - objabi.ElfRelocOffset {
136+
case objabi.RelocType(elf.R_LARCH_PCALA_HI20):
137+
relocType = objabi.R_LOONG64_ADDR_HI
138+
case objabi.RelocType(elf.R_LARCH_PCALA_LO12):
139+
relocType = objabi.R_LOONG64_ADDR_LO
140+
case objabi.RelocType(elf.R_LARCH_PCREL20_S2):
141+
relocType = objabi.R_LOONG64_ADDR_PCREL20_S2
133142
}
143+
su := ldr.MakeSymbolUpdater(s)
144+
su.SetRelocType(rIdx, relocType)
134145
return true
135146

136147
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,
418429
out.Write64(uint64(elf.R_LARCH_B26) | uint64(elfsym)<<32)
419430
out.Write64(uint64(r.Xadd))
420431

432+
case objabi.R_LOONG64_CALL36:
433+
out.Write64(uint64(sectoff))
434+
out.Write64(uint64(elf.R_LARCH_CALL36) | uint64(elfsym)<<32)
435+
out.Write64(uint64(r.Xadd))
436+
421437
case objabi.R_LOONG64_TLS_IE_HI:
422438
out.Write64(uint64(sectoff))
423439
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,
438454
out.Write64(uint64(elf.R_LARCH_PCALA_HI20) | uint64(elfsym)<<32)
439455
out.Write64(uint64(r.Xadd))
440456

457+
case objabi.R_LOONG64_ADDR_PCREL20_S2:
458+
out.Write64(uint64(sectoff))
459+
out.Write64(uint64(elf.R_LARCH_PCREL20_S2) | uint64(elfsym)<<32)
460+
out.Write64(uint64(r.Xadd))
461+
441462
case objabi.R_LOONG64_GOT_HI:
442463
out.Write64(uint64(sectoff))
443464
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
463484
default:
464485
return val, 0, false
465486
case objabi.R_LOONG64_ADDR_HI,
466-
objabi.R_LOONG64_ADDR_LO:
487+
objabi.R_LOONG64_ADDR_LO,
488+
objabi.R_LOONG64_ADDR_PCREL20_S2:
467489
// set up addend for eventual relocation via outer symbol.
468490
rs, _ := ld.FoldSubSymbolOffset(ldr, rs)
469491
rst := ldr.SymType(rs)
@@ -474,6 +496,7 @@ func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loade
474496
case objabi.R_LOONG64_TLS_LE_HI,
475497
objabi.R_LOONG64_TLS_LE_LO,
476498
objabi.R_CALLLOONG64,
499+
objabi.R_LOONG64_CALL36,
477500
objabi.R_JMPLOONG64,
478501
objabi.R_LOONG64_TLS_IE_HI,
479502
objabi.R_LOONG64_TLS_IE_LO,
@@ -499,6 +522,10 @@ func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loade
499522
return val&0xffc003ff | (t << 10), noExtReloc, isOk
500523
}
501524
return val&0xfe00001f | (t << 5), noExtReloc, isOk
525+
case objabi.R_LOONG64_ADDR_PCREL20_S2:
526+
pc := ldr.SymValue(s) + int64(r.Off())
527+
t := (ldr.SymAddr(rs) + r.Add() - pc) >> 2
528+
return val&0xfe00001f | ((t & 0xfffff) << 5), noExtReloc, isOk
502529
case objabi.R_LOONG64_TLS_LE_HI,
503530
objabi.R_LOONG64_TLS_LE_LO:
504531
t := ldr.SymAddr(rs) + r.Add()
@@ -512,6 +539,14 @@ func archreloc(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, r loade
512539
t := ldr.SymAddr(rs) + r.Add() - pc
513540
return val&0xfc000000 | (((t >> 2) & 0xffff) << 10) | (((t >> 2) & 0x3ff0000) >> 16), noExtReloc, isOk
514541

542+
case objabi.R_LOONG64_CALL36:
543+
pc := ldr.SymValue(s) + int64(r.Off())
544+
t := (ldr.SymAddr(rs) + r.Add() - pc) >> 2
545+
// val is pcaddu18i (lower half) + jirl (upper half)
546+
pcaddu18i := (val & 0xfe00001f) | (((t + 0x8000) >> 16) << 5)
547+
jirl := ((val >> 32) & 0xfc0003ff) | ((t & 0xffff) << 10)
548+
return pcaddu18i | (jirl << 32), noExtReloc, isOk
549+
515550
case objabi.R_JMP16LOONG64,
516551
objabi.R_JMP21LOONG64:
517552
pc := ldr.SymValue(s) + int64(r.Off())

0 commit comments

Comments
 (0)