diff --git a/src/cmd/link/internal/loader/loader.go b/src/cmd/link/internal/loader/loader.go
index b28ba467dd081463a1b395c7afa03407a063763a..911fe69ec755c56e3bae0a371f112a89675851ef 100644
--- a/src/cmd/link/internal/loader/loader.go
+++ b/src/cmd/link/internal/loader/loader.go
@@ -15,6 +15,7 @@ import (
 	"cmd/link/internal/sym"
 	"fmt"
 	"log"
+	"math/bits"
 	"os"
 	"sort"
 	"strconv"
@@ -193,6 +194,8 @@ type Loader struct {
 	outer map[Sym]Sym
 	sub   map[Sym]Sym
 
+	align map[Sym]int32 // stores alignment for symbols
+
 	// Used to implement field tracking; created during deadcode if
 	// field tracking is enabled. Reachparent[K] contains the index of
 	// the symbol that triggered the marking of symbol K as live.
@@ -230,6 +233,7 @@ func NewLoader(flags uint32) *Loader {
 		objByPkg:      make(map[string]*oReader),
 		outer:         make(map[Sym]Sym),
 		sub:           make(map[Sym]Sym),
+		align:         make(map[Sym]int32),
 		overwrite:     make(map[Sym]Sym),
 		itablink:      make(map[Sym]struct{}),
 		extStaticSyms: make(map[nameVer]Sym),
@@ -906,6 +910,40 @@ func (l *Loader) Data(i Sym) []byte {
 	return r.Data(li)
 }
 
+// SymAlign returns the alignment for a symbol.
+func (l *Loader) SymAlign(i Sym) int32 {
+	// If an alignment has been recorded, return that.
+	if align, ok := l.align[i]; ok {
+		return align
+	}
+	// TODO: would it make sense to return an arch-specific
+	// alignment depending on section type? E.g. STEXT => 32,
+	// SDATA => 1, etc?
+	return 0
+}
+
+// SetSymAlign sets the alignment for a symbol.
+func (l *Loader) SetSymAlign(i Sym, align int32) {
+	// reject bad synbols
+	if i > l.max || i == 0 {
+		panic("bad symbol index in SetSymAlign")
+	}
+	// Reject nonsense alignments.
+	// TODO: do we need this?
+	if align < 0 {
+		panic("bad alignment value")
+	}
+	if align == 0 {
+		delete(l.align, i)
+	} else {
+		// Alignment should be a power of 2.
+		if bits.OnesCount32(uint32(align)) != 1 {
+			panic("bad alignment value")
+		}
+		l.align[i] = align
+	}
+}
+
 // Returns the number of aux symbols given a global index.
 func (l *Loader) NAux(i Sym) int {
 	if l.IsExternal(i) {
diff --git a/src/cmd/link/internal/loader/loader_test.go b/src/cmd/link/internal/loader/loader_test.go
index a2967831e8d006ba7698c3fbeb6b2390be80bee5..92ade70b8f2c8f1abd2df2795a779b6ab5bfc360 100644
--- a/src/cmd/link/internal/loader/loader_test.go
+++ b/src/cmd/link/internal/loader/loader_test.go
@@ -109,6 +109,17 @@ func TestAddMaterializedSymbol(t *testing.T) {
 			t.Errorf("ldr.SetValue(%d,%d): expected %d got %d\n", s, nv, nv, v)
 		}
 	}
+
+	// Check/set alignment
+	es3al := ldr.SymAlign(es3)
+	if es3al != 0 {
+		t.Errorf("SymAlign(es3): expected 0, got %d", es3al)
+	}
+	ldr.SetSymAlign(es3, 128)
+	es3al = ldr.SymAlign(es3)
+	if es3al != 128 {
+		t.Errorf("SymAlign(es3): expected 128, got %d", es3al)
+	}
 }
 
 func TestOuterSub(t *testing.T) {