Index: src/cmd/link/internal/riscv64/asm.go
--- src/cmd/link/internal/riscv64/asm.go.orig
+++ src/cmd/link/internal/riscv64/asm.go
@@ -20,9 +20,146 @@ import (
 // fakeLabelName matches the RISCV_FAKE_LABEL_NAME from binutils.
 const fakeLabelName = ".L0 "
 
-func gentext(ctxt *ld.Link, ldr *loader.Loader) {
+func gentext(ctxt *ld.Link, ldr *loader.Loader) {}
+
+func findHI20Reloc(ldr *loader.Loader, s loader.Sym, val int64) *loader.Reloc {
+	outer := ldr.OuterSym(s)
+	if outer == 0 {
+		return nil
+	}
+	relocs := ldr.Relocs(outer)
+	start := sort.Search(relocs.Count(), func(i int) bool { return ldr.SymValue(outer)+int64(relocs.At(i).Off()) >= val })
+	for idx := start; idx < relocs.Count(); idx++ {
+		r := relocs.At(idx)
+		if ldr.SymValue(outer)+int64(r.Off()) != val {
+			break
+		}
+		if r.Type() == objabi.R_RISCV_GOT_HI20 || r.Type() == objabi.R_RISCV_PCREL_HI20 {
+			return &r
+		}
+	}
+	return nil
 }
 
+func adddynrel(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loader.Sym, r loader.Reloc, rIdx int) bool {
+	targ := r.Sym()
+
+	var targType sym.SymKind
+	if targ != 0 {
+		targType = ldr.SymType(targ)
+	}
+
+	switch r.Type() {
+	case objabi.ElfRelocOffset + objabi.RelocType(elf.R_RISCV_CALL),
+		objabi.ElfRelocOffset + objabi.RelocType(elf.R_RISCV_CALL_PLT):
+
+		if targType == sym.SDYNIMPORT {
+			addpltsym(target, ldr, syms, targ)
+			su := ldr.MakeSymbolUpdater(s)
+			su.SetRelocSym(rIdx, syms.PLT)
+			su.SetRelocAdd(rIdx, r.Add()+int64(ldr.SymPlt(targ)))
+		}
+		if (targType == 0 || targType == sym.SXREF) && !ldr.AttrVisibilityHidden(targ) {
+			ldr.Errorf(s, "unknown symbol %s in RISCV call", ldr.SymName(targ))
+		}
+		su := ldr.MakeSymbolUpdater(s)
+		su.SetRelocType(rIdx, objabi.R_RISCV_PCREL_ITYPE)
+		return true
+
+	case objabi.ElfRelocOffset + objabi.RelocType(elf.R_RISCV_GOT_HI20):
+		if targType != sym.SDYNIMPORT {
+			// TODO(jsing): Could convert to non-GOT reference.
+		}
+
+		ld.AddGotSym(target, ldr, syms, targ, uint32(elf.R_RISCV_64))
+		su := ldr.MakeSymbolUpdater(s)
+		su.SetRelocType(rIdx, objabi.R_RISCV_GOT_HI20)
+		su.SetRelocSym(rIdx, syms.GOT)
+		su.SetRelocAdd(rIdx, r.Add()+int64(ldr.SymGot(targ)))
+		return true
+
+	case objabi.ElfRelocOffset + objabi.RelocType(elf.R_RISCV_PCREL_HI20):
+		su := ldr.MakeSymbolUpdater(s)
+		su.SetRelocType(rIdx, objabi.R_RISCV_PCREL_HI20)
+		return true
+
+	case objabi.ElfRelocOffset + objabi.RelocType(elf.R_RISCV_PCREL_LO12_I):
+		if r.Add() != 0 {
+			ldr.Errorf(s, "R_RISCV_PCREL_LO12_I with non-zero addend")
+		}
+		su := ldr.MakeSymbolUpdater(s)
+		su.SetRelocType(rIdx, objabi.R_RISCV_PCREL_LO12_I)
+		return true
+
+	case objabi.ElfRelocOffset + objabi.RelocType(elf.R_RISCV_PCREL_LO12_S):
+		if r.Add() != 0 {
+			ldr.Errorf(s, "R_RISCV_PCREL_LO12_S with non-zero addend")
+		}
+		su := ldr.MakeSymbolUpdater(s)
+		su.SetRelocType(rIdx, objabi.R_RISCV_PCREL_LO12_S)
+		return true
+
+	case objabi.ElfRelocOffset + objabi.RelocType(elf.R_RISCV_32_PCREL):
+		su := ldr.MakeSymbolUpdater(s)
+		su.SetRelocType(rIdx, objabi.R_RISCV_PCREL_32)
+		return true
+
+	case objabi.ElfRelocOffset + objabi.RelocType(elf.R_RISCV_RVC_BRANCH):
+		su := ldr.MakeSymbolUpdater(s)
+		su.SetRelocType(rIdx, objabi.R_RISCV_RVC_BRANCH)
+		return true
+
+	case objabi.ElfRelocOffset + objabi.RelocType(elf.R_RISCV_RVC_JUMP):
+		su := ldr.MakeSymbolUpdater(s)
+		su.SetRelocType(rIdx, objabi.R_RISCV_RVC_JUMP)
+		return true
+
+	case objabi.ElfRelocOffset + objabi.RelocType(elf.R_RISCV_BRANCH):
+		su := ldr.MakeSymbolUpdater(s)
+		su.SetRelocType(rIdx, objabi.R_RISCV_BRANCH)
+		return true
+
+	case objabi.ElfRelocOffset + objabi.RelocType(elf.R_RISCV_RELAX):
+		// Ignore relaxations, at least for now.
+		return true
+
+	default:
+		if r.Type() >= objabi.ElfRelocOffset {
+			ldr.Errorf(s, "unexpected relocation type %d (%s)", r.Type(), sym.RelocName(target.Arch, r.Type()))
+			return false
+		}
+	}
+
+	// Reread the reloc to incorporate any changes in type above.
+	relocs := ldr.Relocs(s)
+	r = relocs.At(rIdx)
+
+	switch r.Type() {
+	case objabi.R_RISCV_PCREL_ITYPE:
+		if targType != sym.SDYNIMPORT {
+			// nothing to do, the relocation will be laid out in reloc
+			return true
+		}
+		if target.IsExternal() {
+			// External linker will do this relocation.
+			return true
+		}
+		// Internal linking.
+		if r.Add() != 0 {
+			ldr.Errorf(s, "PLT reference with non-zero addend (%v)", r.Add())
+		}
+		// Build a PLT entry and change the relocation target to that entry.
+		addpltsym(target, ldr, syms, targ)
+		su := ldr.MakeSymbolUpdater(s)
+		su.SetRelocSym(rIdx, syms.PLT)
+		su.SetRelocAdd(rIdx, int64(ldr.SymPlt(targ)))
+
+		return true
+	}
+
+	return false
+}
+
 func genSymsLate(ctxt *ld.Link, ldr *loader.Loader) {
 	if ctxt.LinkMode != ld.LinkExternal {
 		return
@@ -39,7 +176,7 @@ func genSymsLate(ctxt *ld.Link, ldr *loader.Loader) {
 		for ri := 0; ri < relocs.Count(); ri++ {
 			r := relocs.At(ri)
 			if r.Type() != objabi.R_RISCV_PCREL_ITYPE && r.Type() != objabi.R_RISCV_PCREL_STYPE &&
-				r.Type() != objabi.R_RISCV_TLS_IE_ITYPE && r.Type() != objabi.R_RISCV_TLS_IE_STYPE {
+				r.Type() != objabi.R_RISCV_TLS_IE {
 				continue
 			}
 			if r.Off() == 0 && ldr.SymType(s) == sym.STEXT {
@@ -101,7 +238,7 @@ func elfreloc1(ctxt *ld.Link, out *ld.OutBuf, ldr *loa
 		out.Write64(uint64(elf.R_RISCV_JAL) | uint64(elfsym)<<32)
 		out.Write64(uint64(r.Xadd))
 
-	case objabi.R_RISCV_PCREL_ITYPE, objabi.R_RISCV_PCREL_STYPE, objabi.R_RISCV_TLS_IE_ITYPE, objabi.R_RISCV_TLS_IE_STYPE:
+	case objabi.R_RISCV_PCREL_ITYPE, objabi.R_RISCV_PCREL_STYPE, objabi.R_RISCV_TLS_IE:
 		// Find the text symbol for the AUIPC instruction targeted
 		// by this relocation.
 		relocs := ldr.Relocs(s)
@@ -127,10 +264,8 @@ func elfreloc1(ctxt *ld.Link, out *ld.OutBuf, ldr *loa
 			hiRel, loRel = elf.R_RISCV_PCREL_HI20, elf.R_RISCV_PCREL_LO12_I
 		case objabi.R_RISCV_PCREL_STYPE:
 			hiRel, loRel = elf.R_RISCV_PCREL_HI20, elf.R_RISCV_PCREL_LO12_S
-		case objabi.R_RISCV_TLS_IE_ITYPE:
+		case objabi.R_RISCV_TLS_IE:
 			hiRel, loRel = elf.R_RISCV_TLS_GOT_HI20, elf.R_RISCV_PCREL_LO12_I
-		case objabi.R_RISCV_TLS_IE_STYPE:
-			hiRel, loRel = elf.R_RISCV_TLS_GOT_HI20, elf.R_RISCV_PCREL_LO12_S
 		}
 		out.Write64(uint64(sectoff))
 		out.Write64(uint64(hiRel) | uint64(elfsym)<<32)
@@ -139,6 +274,17 @@ func elfreloc1(ctxt *ld.Link, out *ld.OutBuf, ldr *loa
 		out.Write64(uint64(loRel) | uint64(hi20ElfSym)<<32)
 		out.Write64(uint64(0))
 
+	case objabi.R_RISCV_TLS_LE:
+		out.Write64(uint64(sectoff))
+		out.Write64(uint64(elf.R_RISCV_TPREL_HI20) | uint64(elfsym)<<32)
+		out.Write64(uint64(r.Xadd))
+		out.Write64(uint64(sectoff + 4))
+		out.Write64(uint64(elf.R_RISCV_TPREL_LO12_I) | uint64(elfsym)<<32)
+		out.Write64(uint64(r.Xadd))
+		out.Write64(uint64(sectoff + 8))
+		out.Write64(uint64(elf.R_RISCV_TPREL_ADD) | uint64(elfsym)<<32)
+		out.Write64(uint64(0))
+
 	default:
 		return false
 	}
@@ -146,10 +292,104 @@ func elfreloc1(ctxt *ld.Link, out *ld.OutBuf, ldr *loa
 	return true
 }
 
-func elfsetupplt(ctxt *ld.Link, plt, gotplt *loader.SymbolBuilder, dynamic loader.Sym) {
-	log.Fatalf("elfsetupplt")
+func elfsetupplt(ctxt *ld.Link, ldr *loader.Loader, plt, gotplt *loader.SymbolBuilder, dynamic loader.Sym) {
+	if plt.Size() != 0 {
+		return
+	}
+	if gotplt.Size() != 0 {
+		ctxt.Errorf(gotplt.Sym(), "got.plt is not empty")
+	}
+
+	// https://github.com/riscv/riscv-elf-psabi-doc/blob/master/riscv-elf.md#program-linkage-table
+	//
+	// 1:   auipc  t2, %pcrel_hi(.got.plt)
+	//      sub    t1, t1, t3               # shifted .got.plt offset + hdr size + 12
+	//      l[w|d] t3, %pcrel_lo(1b)(t2)    # _dl_runtime_resolve
+	//      addi   t1, t1, -(hdr size + 12) # shifted .got.plt offset
+	//      addi   t0, t2, %pcrel_lo(1b)    # &.got.plt
+	//      srli   t1, t1, log2(16/PTRSIZE) # .got.plt offset
+	//      l[w|d] t0, PTRSIZE(t0)          # link map
+	//      jr     t3
+
+	plt.AddSymRef(ctxt.Arch, gotplt.Sym(), 0, objabi.R_RISCV_PCREL_HI20, 4)
+	plt.SetUint32(ctxt.Arch, plt.Size()-4, 0x00000397) // auipc   t2,0x0
+
+	sb := ldr.MakeSymbolBuilder(fakeLabelName)
+	sb.SetType(sym.STEXT)
+	sb.SetValue(ldr.SymValue(plt.Sym()) + plt.Size() - 4)
+	sb.SetLocal(true)
+	sb.SetReachable(true)
+	sb.SetVisibilityHidden(true)
+	plt.AddInteriorSym(sb.Sym())
+
+	plt.AddUint32(ctxt.Arch, 0x41c30333) // sub     t1,t1,t3
+
+	plt.AddSymRef(ctxt.Arch, sb.Sym(), 0, objabi.R_RISCV_PCREL_LO12_I, 4)
+	plt.SetUint32(ctxt.Arch, plt.Size()-4, 0x0003be03) // ld      t3,0(t2)
+
+	plt.AddUint32(ctxt.Arch, 0xfd430313) // addi    t1,t1,-44
+
+	plt.AddSymRef(ctxt.Arch, sb.Sym(), 0, objabi.R_RISCV_PCREL_LO12_I, 4)
+	plt.SetUint32(ctxt.Arch, plt.Size()-4, 0x00038293) // addi    t0,t2,0
+
+	plt.AddUint32(ctxt.Arch, 0x00135313) // srli    t1,t1,0x1
+	plt.AddUint32(ctxt.Arch, 0x0082b283) // ld      t0,8(t0)
+	plt.AddUint32(ctxt.Arch, 0x00008e02) // jr      t3
+
+	gotplt.AddAddrPlus(ctxt.Arch, dynamic, 0) // got.plt[0] = _dl_runtime_resolve
+	gotplt.AddUint64(ctxt.Arch, 0)            // got.plt[1] = link map
 }
 
+func addpltsym(target *ld.Target, ldr *loader.Loader, syms *ld.ArchSyms, s loader.Sym) {
+	if ldr.SymPlt(s) >= 0 {
+		return
+	}
+
+	ld.Adddynsym(ldr, target, syms, s)
+
+	plt := ldr.MakeSymbolUpdater(syms.PLT)
+	gotplt := ldr.MakeSymbolUpdater(syms.GOTPLT)
+	rela := ldr.MakeSymbolUpdater(syms.RelaPLT)
+	if plt.Size() == 0 {
+		panic("plt is not set up")
+	}
+
+	// https://github.com/riscv/riscv-elf-psabi-doc/blob/master/riscv-elf.md#program-linkage-table
+	//
+	// 1:  auipc   t3, %pcrel_hi(function@.got.plt)
+	//     l[w|d]  t3, %pcrel_lo(1b)(t3)
+	//     jalr    t1, t3
+	//     nop
+
+	plt.AddSymRef(target.Arch, gotplt.Sym(), gotplt.Size(), objabi.R_RISCV_PCREL_HI20, 4)
+	plt.SetUint32(target.Arch, plt.Size()-4, 0x00000e17) // auipc   t3,0x0
+
+	sb := ldr.MakeSymbolBuilder(fakeLabelName)
+	sb.SetType(sym.STEXT)
+	sb.SetValue(ldr.SymValue(plt.Sym()) + plt.Size() - 4)
+	sb.SetLocal(true)
+	sb.SetReachable(true)
+	sb.SetVisibilityHidden(true)
+	plt.AddInteriorSym(sb.Sym())
+
+	plt.AddSymRef(target.Arch, sb.Sym(), 0, objabi.R_RISCV_PCREL_LO12_I, 4)
+	plt.SetUint32(target.Arch, plt.Size()-4, 0x000e3e03) // ld      t3,0(t3)
+	plt.AddUint32(target.Arch, 0x000e0367)               // jalr    t1,t3
+	plt.AddUint32(target.Arch, 0x00000001)               // nop
+
+	ldr.SetPlt(s, int32(plt.Size()-16))
+
+	// add to got.plt: pointer to plt[0]
+	gotplt.AddAddrPlus(target.Arch, plt.Sym(), 0)
+
+	// rela
+	rela.AddAddrPlus(target.Arch, gotplt.Sym(), gotplt.Size()-8)
+	sDynid := ldr.SymDynid(s)
+
+	rela.AddUint64(target.Arch, elf.R_INFO(uint32(sDynid), uint32(elf.R_RISCV_JUMP_SLOT)))
+	rela.AddUint64(target.Arch, 0)
+}
+
 func machoreloc1(*sys.Arch, *ld.OutBuf, *loader.Loader, loader.Sym, loader.ExtReloc, int64) bool {
 	log.Fatalf("machoreloc1 not implemented")
 	return false
@@ -189,8 +429,11 @@ func archreloc(target *ld.Target, ldr *loader.Loader, 
 		case objabi.R_RISCV_CALL, objabi.R_RISCV_CALL_TRAMP:
 			return val, 1, true
 
-		case objabi.R_RISCV_PCREL_ITYPE, objabi.R_RISCV_PCREL_STYPE, objabi.R_RISCV_TLS_IE_ITYPE, objabi.R_RISCV_TLS_IE_STYPE:
+		case objabi.R_RISCV_PCREL_ITYPE, objabi.R_RISCV_PCREL_STYPE, objabi.R_RISCV_TLS_IE:
 			return val, 2, true
+
+		case objabi.R_RISCV_TLS_LE:
+			return val, 3, true
 		}
 
 		return val, 0, false
@@ -211,16 +454,132 @@ func archreloc(target *ld.Target, ldr *loader.Loader, 
 
 		return val, 0, true
 
-	case objabi.R_RISCV_TLS_IE_ITYPE, objabi.R_RISCV_TLS_IE_STYPE:
-		// TLS relocations are not currently handled for internal linking.
-		// For now, TLS is only used when cgo is in use and cgo currently
-		// requires external linking. However, we need to accept these
-		// relocations so that code containing TLS variables will link,
-		// even when they're not being used. For now, replace these
-		// instructions with EBREAK to detect accidental use.
-		const ebreakIns = 0x00100073
-		return ebreakIns<<32 | ebreakIns, 0, true
+	case objabi.R_RISCV_TLS_IE:
+		log.Fatalf("cannot handle R_RISCV_TLS_IE (sym %s) when linking internally", ldr.SymName(s))
+		return val, 0, false
 
+	case objabi.R_RISCV_TLS_LE:
+		// Generate LUI and ADDIW instruction immediates.
+		off := r.Add()
+
+		low, high, err := riscv.Split32BitImmediate(off)
+		if err != nil {
+			ldr.Errorf(s, "relocation does not fit in 32-bits: %d", off)
+		}
+
+		luiImm, err := riscv.EncodeUImmediate(high)
+		if err != nil {
+			ldr.Errorf(s, "cannot encode R_RISCV_TLS_LE LUI relocation offset for %s: %v", ldr.SymName(rs), err)
+		}
+
+		addiwImm, err := riscv.EncodeIImmediate(low)
+		if err != nil {
+			ldr.Errorf(s, "cannot encode R_RISCV_TLS_LE I-type instruction relocation offset for %s: %v", ldr.SymName(rs), err)
+		}
+
+		lui := int64(uint32(val))
+		addiw := int64(uint32(val >> 32))
+
+		lui = (lui &^ riscv.UTypeImmMask) | int64(uint32(luiImm))
+		addiw = (addiw &^ riscv.ITypeImmMask) | int64(uint32(addiwImm))
+
+		return addiw<<32 | lui, 0, true
+
+	case objabi.R_RISCV_BRANCH:
+		pc := ldr.SymValue(s) + int64(r.Off())
+		off := ldr.SymValue(rs) + r.Add() - pc
+
+		imm, err := riscv.EncodeBImmediate(off)
+		if err != nil {
+			ldr.Errorf(s, "cannot encode B-type instruction relocation offset for %s: %v", ldr.SymName(rs), err)
+		}
+		ins := (int64(uint32(val)) &^ riscv.BTypeImmMask) | int64(uint32(imm))
+
+		return ins, 0, true
+
+	case objabi.R_RISCV_RVC_BRANCH, objabi.R_RISCV_RVC_JUMP:
+		pc := ldr.SymValue(s) + int64(r.Off())
+		off := ldr.SymValue(rs) + r.Add() - pc
+
+		var err error
+		var imm, immMask int64
+		switch r.Type() {
+		case objabi.R_RISCV_RVC_BRANCH:
+			immMask = riscv.CBTypeImmMask
+			imm, err = riscv.EncodeCBImmediate(off)
+			if err != nil {
+				ldr.Errorf(s, "cannot encode CB-type instruction relocation offset for %s: %v", ldr.SymName(rs), err)
+			}
+		case objabi.R_RISCV_RVC_JUMP:
+			immMask = riscv.CJTypeImmMask
+			imm, err = riscv.EncodeCJImmediate(off)
+			if err != nil {
+				ldr.Errorf(s, "cannot encode CJ-type instruction relocation offset for %s: %v", ldr.SymName(rs), err)
+			}
+		default:
+			panic(fmt.Sprintf("unknown relocation type: %v", r.Type()))
+		}
+
+		ins := (int64(uint16(val)) &^ immMask) | int64(uint16(imm))
+
+		return ins, 0, true
+
+	case objabi.R_RISCV_GOT_HI20, objabi.R_RISCV_PCREL_HI20:
+		pc := ldr.SymValue(s) + int64(r.Off())
+		off := ldr.SymValue(rs) + r.Add() - pc
+
+		// Generate AUIPC immediates.
+		_, high, err := riscv.Split32BitImmediate(off)
+		if err != nil {
+			ldr.Errorf(s, "relocation does not fit in 32-bits: %d", off)
+		}
+
+		auipcImm, err := riscv.EncodeUImmediate(high)
+		if err != nil {
+			ldr.Errorf(s, "cannot encode R_RISCV_PCREL_ AUIPC relocation offset for %s: %v", ldr.SymName(rs), err)
+		}
+
+		auipc := int64(uint32(val))
+		auipc = (auipc &^ riscv.UTypeImmMask) | int64(uint32(auipcImm))
+
+		return auipc, 0, true
+
+	case objabi.R_RISCV_PCREL_LO12_I, objabi.R_RISCV_PCREL_LO12_S:
+		hi20Reloc := findHI20Reloc(ldr, rs, ldr.SymValue(rs))
+		if hi20Reloc == nil {
+			ldr.Errorf(s, "missing HI20 relocation for LO12 relocation with %s (%d)", ldr.SymName(rs), rs)
+		}
+
+		pc := ldr.SymValue(s) + int64(hi20Reloc.Off())
+		off := ldr.SymValue(hi20Reloc.Sym()) + hi20Reloc.Add() - pc
+
+		low, _, err := riscv.Split32BitImmediate(off)
+		if err != nil {
+			ldr.Errorf(s, "relocation does not fit in 32-bits: %d", off)
+		}
+
+		var imm, immMask int64
+		switch r.Type() {
+		case objabi.R_RISCV_PCREL_LO12_I:
+			immMask = riscv.ITypeImmMask
+			imm, err = riscv.EncodeIImmediate(low)
+			if err != nil {
+				ldr.Errorf(s, "cannot encode objabi.R_RISCV_PCREL_LO12_I I-type instruction relocation offset for %s: %v", ldr.SymName(rs), err)
+			}
+		case objabi.R_RISCV_PCREL_LO12_S:
+			immMask = riscv.STypeImmMask
+			imm, err = riscv.EncodeSImmediate(low)
+			if err != nil {
+				ldr.Errorf(s, "cannot encode R_RISCV_PCREL_LO12_S S-type instruction relocation offset for %s: %v", ldr.SymName(rs), err)
+			}
+		default:
+			panic(fmt.Sprintf("unknown relocation type: %v", r.Type()))
+		}
+
+		second := int64(uint32(val))
+		second = (second &^ immMask) | int64(uint32(imm))
+		return second, 0, true
+
 	case objabi.R_RISCV_PCREL_ITYPE, objabi.R_RISCV_PCREL_STYPE:
 		// Generate AUIPC and second instruction immediates.
 		low, high, err := riscv.Split32BitImmediate(off)
@@ -248,7 +607,7 @@ func archreloc(target *ld.Target, ldr *loader.Loader, 
 				ldr.Errorf(s, "cannot encode R_RISCV_PCREL_STYPE S-type instruction relocation offset for %s: %v", ldr.SymName(rs), err)
 			}
 		default:
-			panic(fmt.Sprintf("Unknown relocation type: %v", r.Type()))
+			panic(fmt.Sprintf("unknown relocation type: %v", r.Type()))
 		}
 
 		auipc := int64(uint32(val))
@@ -258,6 +617,11 @@ func archreloc(target *ld.Target, ldr *loader.Loader, 
 		second = (second &^ secondImmMask) | int64(uint32(secondImm))
 
 		return second<<32 | auipc, 0, true
+
+	case objabi.R_RISCV_PCREL_32:
+		pc := ldr.SymValue(s) + int64(r.Off())
+		off := ldr.SymValue(rs) + r.Add() - pc
+		return off, 0, true
 	}
 
 	return val, 0, false
@@ -273,7 +637,7 @@ func extreloc(target *ld.Target, ldr *loader.Loader, r
 	case objabi.R_RISCV_CALL, objabi.R_RISCV_CALL_TRAMP:
 		return ld.ExtrelocSimple(ldr, r), true
 
-	case objabi.R_RISCV_PCREL_ITYPE, objabi.R_RISCV_PCREL_STYPE, objabi.R_RISCV_TLS_IE_ITYPE, objabi.R_RISCV_TLS_IE_STYPE:
+	case objabi.R_RISCV_PCREL_ITYPE, objabi.R_RISCV_PCREL_STYPE, objabi.R_RISCV_TLS_IE, objabi.R_RISCV_TLS_LE:
 		return ld.ExtrelocViaOuterSym(ldr, r, s), true
 	}
 	return loader.ExtReloc{}, false
@@ -352,7 +716,7 @@ func trampoline(ctxt *ld.Link, ldr *loader.Loader, ri 
 
 func genCallTramp(arch *sys.Arch, linkmode ld.LinkMode, ldr *loader.Loader, tramp *loader.SymbolBuilder, target loader.Sym, offset int64) {
 	tramp.AddUint32(arch, 0x00000f97) // AUIPC	$0, X31
-	tramp.AddUint32(arch, 0x000f8067) // JALR		X0, (X31)
+	tramp.AddUint32(arch, 0x000f8067) // JALR	X0, (X31)
 
 	r, _ := tramp.AddRel(objabi.R_RISCV_PCREL_ITYPE)
 	r.SetSiz(8)
