lsym := base.Ctxt.Lookup(lv.fn.LSym.Name + ".argliveinfo")
lsym.Set(obj.AttrContentAddressable, true)
+ lsym.Align = 1
off := objw.Uint8(lsym, 0, argOffsets[0]) // smallest offset that needs liveness info.
for idx, live := range livenessMaps {
// Format must match runtime/stack.go:stackObjectRecord.
x := base.Ctxt.Lookup(lv.fn.LSym.Name + ".stkobj")
x.Set(obj.AttrContentAddressable, true)
+ x.Align = 4
lv.fn.LSym.Func().StackObjects = x
off := 0
off = objw.Uintptr(x, off, uint64(len(vars)))
ot := dnameData(s, 0, p.Path, "", nil, false, false)
objw.Global(s, int32(ot), obj.DUPOK|obj.RODATA)
s.Set(obj.AttrContentAddressable, true)
+ s.Align = 1
p.Pathsym = s
}
ot := dnameData(s, 0, name, tag, pkg, exported, embedded)
objw.Global(s, int32(ot), obj.DUPOK|obj.RODATA)
s.Set(obj.AttrContentAddressable, true)
+ s.Align = 1
return s
}
// Nothing writes static itabs, so they are read only.
objw.Global(lsym, int32(rttype.ITab.Size()+delta), int16(obj.DUPOK|obj.RODATA))
lsym.Set(obj.AttrContentAddressable, true)
+ lsym.Align = int16(types.PtrSize)
}
func WritePluginTable() {
}
objw.Global(lsym, int32(len(ptrmask)), obj.DUPOK|obj.RODATA|obj.LOCAL)
lsym.Set(obj.AttrContentAddressable, true)
+ // The runtime expects ptrmasks to be aligned
+ // as a uintptr.
+ lsym.Align = int16(types.PtrSize)
}
return lsym
}
x := base.Ctxt.Lookup(s.curfn.LSym.Name + ".opendefer")
x.Set(obj.AttrContentAddressable, true)
+ x.Align = 1
s.curfn.LSym.Func().OpenCodedDeferInfo = x
off := 0
// emit argument info (locations on stack) of f for traceback.
func EmitArgInfo(f *ir.Func, abiInfo *abi.ABIParamResultInfo) *obj.LSym {
x := base.Ctxt.Lookup(fmt.Sprintf("%s.arginfo%d", f.LSym.Name, f.ABI))
+ x.Align = 1
// NOTE: do not set ContentAddressable here. This may be referenced from
// assembly code by name (in this case f is a declaration).
// Instead, set it in emitArgInfo above.
x := base.Ctxt.LookupInit(fmt.Sprintf("%s.wrapinfo", wsym.Name), func(x *obj.LSym) {
objw.SymPtrOff(x, 0, wsym)
x.Set(obj.AttrContentAddressable, true)
+ x.Align = 4
})
e.curfn.LSym.Func().WrapInfo = x
off := dstringdata(symdata, 0, s, pos, "string")
objw.Global(symdata, int32(off), obj.DUPOK|obj.RODATA|obj.LOCAL)
symdata.Set(obj.AttrContentAddressable, true)
+ symdata.Align = 1
}
return symdata
info.Name = file
info.Size = size
objw.Global(symdata, int32(size), obj.DUPOK|obj.RODATA|obj.LOCAL)
+ symdata.Align = 1
// Note: AttrContentAddressable cannot be set here,
// because the content-addressable-handling code
// does not know about file symbols.
lsym := types.LocalPkg.Lookup(symname).LinksymABI(obj.ABI0)
off := dstringdata(lsym, 0, s, pos, "slice")
objw.Global(lsym, int32(off), obj.NOPTR|obj.LOCAL)
+ lsym.Align = 1
return lsym
}
typecheck.Target.Externs = append(typecheck.Target.Externs, n)
n.Linksym().Set(obj.AttrStatic, true)
+ n.Linksym().Align = int16(t.Alignment())
+
return n
}
"math"
"math/bits"
"slices"
- "strings"
)
// ctxt7 holds state while assembling a single function.
// to decide whether to use the unaligned/aligned forms, so o.size's result is always
// in sync with the code generation decisions, because it *is* the code generation decision.
align := int64(1 << sz)
- if o.a1 == C_ADDR && p.From.Offset%align == 0 && symAlign(p.From.Sym) >= align ||
- o.a4 == C_ADDR && p.To.Offset%align == 0 && symAlign(p.To.Sym) >= align {
+ if o.a1 == C_ADDR && p.From.Offset%align == 0 && int64(p.From.Sym.Align) >= align ||
+ o.a4 == C_ADDR && p.To.Offset%align == 0 && int64(p.To.Sym.Align) >= align {
return 8
}
}
return int(o.size_)
}
-// symAlign returns the expected symbol alignment of the symbol s.
-// This must match the linker's own default alignment decisions.
-func symAlign(s *obj.LSym) int64 {
- name := s.Name
- switch {
- case strings.HasPrefix(name, "go:string."),
- strings.HasPrefix(name, "type:.namedata."),
- strings.HasPrefix(name, "type:.importpath."),
- strings.HasSuffix(name, ".opendefer"),
- strings.HasSuffix(name, ".arginfo0"),
- strings.HasSuffix(name, ".arginfo1"),
- strings.HasSuffix(name, ".argliveinfo"):
- // These are just bytes, or varints.
- return 1
- case strings.HasPrefix(name, "gclocals·"):
- // It has 32-bit fields.
- return 4
- default:
- switch {
- case s.Size%8 == 0:
- return 8
- case s.Size%4 == 0:
- return 4
- case s.Size%2 == 0:
- return 2
- }
- }
- return 1
-}
-
func span7(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
if ctxt.Retpoline {
ctxt.Diag("-spectre=ret not supported on arm64")
}
align := uint32(s.Align)
if s.ContentAddressable() && s.Size != 0 && align == 0 {
- // We generally assume data symbols are naturally aligned
- // (e.g. integer constants), except for strings and a few
- // compiler-emitted funcdata. If we dedup a string symbol and
- // a non-string symbol with the same content, we should keep
- // the largest alignment.
- // TODO: maybe the compiler could set the alignment for all
- // data symbols more carefully.
- switch {
- case strings.HasPrefix(s.Name, "go:string."),
- strings.HasPrefix(name, "type:.namedata."),
- strings.HasPrefix(name, "type:.importpath."),
- strings.HasSuffix(name, ".opendefer"),
- strings.HasSuffix(name, ".arginfo0"),
- strings.HasSuffix(name, ".arginfo1"),
- strings.HasSuffix(name, ".argliveinfo"):
- // These are just bytes, or varints.
- align = 1
- case strings.HasPrefix(name, "gclocals·"):
- // It has 32-bit fields.
- align = 4
- default:
- switch {
- case w.ctxt.Arch.PtrSize == 8 && s.Size%8 == 0:
- align = 8
- case s.Size%4 == 0:
- align = 4
- case s.Size%2 == 0:
- align = 2
- default:
- align = 1
- }
- }
+ // TODO: Check that alignment is set for all symbols.
+ w.ctxt.Diag("%s: is content-addressable but alignment is not set (size is %d)", s.Name, s.Size)
}
if s.Size > cutoff {
w.ctxt.Diag("%s: symbol too large (%d bytes > %d bytes)", s.Name, s.Size, cutoff)
sym := &LSym{
Type: objabi.SRODATA,
Attribute: AttrContentAddressable | AttrPcdata,
+ Align: 1,
}
if dbg {
pcln.Pcdata[i] = &LSym{
Type: objabi.SRODATA,
Attribute: AttrContentAddressable | AttrPcdata,
+ Align: 1,
}
} else {
pcln.Pcdata[i] = funcpctab(ctxt, cursym, "pctopcdata", pctopcdata, any(uint32(i)))
name := fmt.Sprintf("$f32.%08x%s", i, suffix)
return ctxt.LookupInit(name, func(s *LSym) {
s.Size = 4
+ s.Align = 4
s.WriteFloat32(ctxt, 0, f)
s.Type = typ
s.Set(AttrLocal, true)
name := fmt.Sprintf("$f64.%016x%s", i, suffix)
return ctxt.LookupInit(name, func(s *LSym) {
s.Size = 8
+ s.Align = int16(ctxt.Arch.PtrSize)
s.WriteFloat64(ctxt, 0, f)
s.Type = typ
s.Set(AttrLocal, true)
name := fmt.Sprintf("$i32.%08x%s", uint64(i), suffix)
return ctxt.LookupInit(name, func(s *LSym) {
s.Size = 4
+ s.Align = 4
s.WriteInt(ctxt, 0, 4, i)
s.Type = typ
s.Set(AttrLocal, true)
name := fmt.Sprintf("$i64.%016x%s", uint64(i), suffix)
return ctxt.LookupInit(name, func(s *LSym) {
s.Size = 8
+ s.Align = int16(ctxt.Arch.PtrSize)
s.WriteInt(ctxt, 0, 8, i)
s.Type = typ
s.Set(AttrLocal, true)
name := fmt.Sprintf("$i128.%016x%016x%s", uint64(hi), uint64(lo), suffix)
return ctxt.LookupInit(name, func(s *LSym) {
s.Size = 16
+ s.Align = int16(ctxt.Arch.PtrSize)
if ctxt.Arch.ByteOrder == binary.LittleEndian {
s.WriteInt(ctxt, 0, 8, lo)
s.WriteInt(ctxt, 8, 8, hi)
return ctxt.LookupInit(fmt.Sprintf("gclocals·%s", str), func(lsym *LSym) {
lsym.P = data
lsym.Set(AttrContentAddressable, true)
+ lsym.Align = 4
})
}
symname := fmt.Sprintf("%d.%s", len(buf.data), hash)
return ctxt.LookupInit("go:sehuw."+symname, func(s *obj.LSym) {
s.WriteBytes(ctxt, 0, buf.data)
+ s.Align = 4
s.Type = objabi.SSEHUNWINDINFO
s.Set(obj.AttrDuplicateOK, true)
s.Set(obj.AttrLocal, true)