return adduintxx(ctxt, s, v, 8)
}
+func adduint(ctxt *Link, s *LSym, v uint64) int64 {
+ return adduintxx(ctxt, s, v, Thearch.Intsize)
+}
+
func setuint8(ctxt *Link, s *LSym, r int64, v uint8) int64 {
return setuintxx(ctxt, s, r, uint64(v), 1)
}
var pclntab_zpcln Pcln
+// These variables are used to initialize runtime.themoduledata, see symtab.go:symtab.
+var pclntabNfunc int32
+var pclntabFiletabOffset int32
+var pclntabPclntabOffset int32
+var pclntabFirstFunc *LSym
+var pclntabLastFunc *LSym
+
func pclntab() {
funcdata_bytes := int64(0)
ftab := Linklookup(Ctxt, "runtime.pclntab", 0)
}
}
+ pclntabNfunc = nfunc
Symgrow(Ctxt, ftab, 8+int64(Thearch.Ptrsize)+int64(nfunc)*2*int64(Thearch.Ptrsize)+int64(Thearch.Ptrsize)+4)
setuint32(Ctxt, ftab, 0, 0xfffffffb)
setuint8(Ctxt, ftab, 6, uint8(Thearch.Minlc))
setuint8(Ctxt, ftab, 7, uint8(Thearch.Ptrsize))
setuintxx(Ctxt, ftab, 8, uint64(nfunc), int64(Thearch.Ptrsize))
+ pclntabPclntabOffset = int32(8 + Thearch.Ptrsize)
nfunc = 0
var last *LSym
pcln = &pclntab_zpcln
}
+ if pclntabFirstFunc == nil {
+ pclntabFirstFunc = Ctxt.Cursym
+ }
+
funcstart = int32(len(ftab.P))
funcstart += int32(-len(ftab.P)) & (int32(Thearch.Ptrsize) - 1)
nfunc++
}
+ pclntabLastFunc = last
// Final entry of table is just end pc.
setaddrplus(Ctxt, ftab, 8+int64(Thearch.Ptrsize)+int64(nfunc)*2*int64(Thearch.Ptrsize), last, last.Size)
start := int32(len(ftab.P))
start += int32(-len(ftab.P)) & (int32(Thearch.Ptrsize) - 1)
+ pclntabFiletabOffset = start
setuint32(Ctxt, ftab, 8+int64(Thearch.Ptrsize)+int64(nfunc)*2*int64(Thearch.Ptrsize)+int64(Thearch.Ptrsize), uint32(start))
Symgrow(Ctxt, ftab, int64(start)+(int64(Ctxt.Nhistfile)+1)*4)
symt.Size = 0
symt.Reachable = true
+ ntypelinks := 0
+
// assign specific types so that they sort together.
// within a type they sort by size, so the .* symbols
// just defined above will be first.
}
if strings.HasPrefix(s.Name, "go.typelink.") {
+ ntypelinks++
s.Type = STYPELINK
s.Hide = 1
s.Outer = symtypelink
// Information about the layout of the executable image for the
// runtime to use. Any changes here must be matched by changes to
// the definition of moduledata in runtime/symtab.go.
+ // This code uses several global variables that are set by pcln.go:pclntab.
moduledata := Linklookup(Ctxt, "runtime.themoduledata", 0)
moduledata.Type = SNOPTRDATA
moduledata.Size = 0 // truncate symbol back to 0 bytes to reinitialize
moduledata.Reachable = true
- // Three slices (pclntable, ftab, filetab), uninitalized
- moduledata.Size += int64((3 * 3 * Thearch.Ptrsize))
- Symgrow(Ctxt, moduledata, moduledata.Size)
- // Three uintptrs, initialized
+ // The pclntab slice
Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.pclntab", 0))
- Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.epclntab", 0))
+ adduint(Ctxt, moduledata, uint64(Linklookup(Ctxt, "runtime.pclntab", 0).Size))
+ adduint(Ctxt, moduledata, uint64(Linklookup(Ctxt, "runtime.pclntab", 0).Size))
+ // The ftab slice
+ Addaddrplus(Ctxt, moduledata, Linklookup(Ctxt, "runtime.pclntab", 0), int64(pclntabPclntabOffset))
+ adduint(Ctxt, moduledata, uint64(pclntabNfunc+1))
+ adduint(Ctxt, moduledata, uint64(pclntabNfunc+1))
+ // The filetab slice
+ Addaddrplus(Ctxt, moduledata, Linklookup(Ctxt, "runtime.pclntab", 0), int64(pclntabFiletabOffset))
+ adduint(Ctxt, moduledata, uint64(Ctxt.Nhistfile))
+ adduint(Ctxt, moduledata, uint64(Ctxt.Nhistfile))
+ // findfunctab
Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.findfunctab", 0))
- // 2 more uintptrs (minpc, maxpc), uninitalized
- moduledata.Size += int64(2 * Thearch.Ptrsize)
- Symgrow(Ctxt, moduledata, moduledata.Size)
- // more initialized uintptrs
+ // minpc, maxpc
+ Addaddr(Ctxt, moduledata, pclntabFirstFunc)
+ Addaddrplus(Ctxt, moduledata, pclntabLastFunc, pclntabLastFunc.Size)
+ // pointers to specific parts of the module
Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.text", 0))
Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.etext", 0))
Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.noptrdata", 0))
Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.end", 0))
Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.gcdata", 0))
Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.gcbss", 0))
+ // The typelinks slice
Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.typelink", 0))
- Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.etypelink", 0))
+ adduint(Ctxt, moduledata, uint64(ntypelinks))
+ adduint(Ctxt, moduledata, uint64(ntypelinks))
}
framepointer_enabled = haveexperiment("framepointer")
tracebackinit()
- symtabinit()
+ symtabverify()
stackinit()
mallocinit()
mcommoninit(_g_.m)
//go:linkname reflect_typelinks reflect.typelinks
//go:nosplit
func reflect_typelinks() []*_type {
- var ret []*_type
- sp := (*slice)(unsafe.Pointer(&ret))
- sp.array = (*byte)(unsafe.Pointer(themoduledata.typelink))
- sp.len = uint((themoduledata.etypelink - themoduledata.typelink) / unsafe.Sizeof(ret[0]))
- sp.cap = sp.len
- return ret
+ return themoduledata.typelinks
}
// TODO: move back into mgc.go
// image. It is written by the linker. Any changes here must be
// matched changes to the code in cmd/internal/ld/symtab.go:symtab.
type moduledata struct {
- pclntable []byte
- ftab []functab
- filetab []uint32
- pclntab, epclntab, findfunctab uintptr
- minpc, maxpc uintptr
+ pclntable []byte
+ ftab []functab
+ filetab []uint32
+ findfunctab uintptr
+ minpc, maxpc uintptr
text, etext uintptr
noptrdata, enoptrdata uintptr
noptrbss, enoptrbss uintptr
end, gcdata, gcbss uintptr
- typelink, etypelink uintptr
+ typelinks []*_type
}
var themoduledata moduledata // linker symbol
subbuckets [16]byte
}
-func symtabinit() {
+func symtabverify() {
// See golang.org/s/go12symtab for header: 0xfffffffb,
// two zero bytes, a byte giving the PC quantum,
// and a byte giving the pointer width in bytes.
- pcln := (*[8]byte)(unsafe.Pointer(themoduledata.pclntab))
- pcln32 := (*[2]uint32)(unsafe.Pointer(themoduledata.pclntab))
+ pcln := *(**[8]byte)(unsafe.Pointer(&themoduledata.pclntable))
+ pcln32 := *(**[2]uint32)(unsafe.Pointer(&themoduledata.pclntable))
if pcln32[0] != 0xfffffffb || pcln[4] != 0 || pcln[5] != 0 || pcln[6] != _PCQuantum || pcln[7] != ptrSize {
println("runtime: function symbol table header:", hex(pcln32[0]), hex(pcln[4]), hex(pcln[5]), hex(pcln[6]), hex(pcln[7]))
throw("invalid function symbol table\n")
}
- // pclntable is all bytes of pclntab symbol.
- sp := (*sliceStruct)(unsafe.Pointer(&themoduledata.pclntable))
- sp.array = unsafe.Pointer(themoduledata.pclntab)
- sp.len = int(uintptr(unsafe.Pointer(themoduledata.epclntab)) - uintptr(unsafe.Pointer(themoduledata.pclntab)))
- sp.cap = sp.len
-
// ftab is lookup table for function by program counter.
- nftab := int(*(*uintptr)(add(unsafe.Pointer(pcln), 8)))
- p := add(unsafe.Pointer(pcln), 8+ptrSize)
- sp = (*sliceStruct)(unsafe.Pointer(&themoduledata.ftab))
- sp.array = p
- sp.len = nftab + 1
- sp.cap = sp.len
+ nftab := len(themoduledata.ftab) - 1
for i := 0; i < nftab; i++ {
// NOTE: ftab[nftab].entry is legal; it is the address beyond the final function.
if themoduledata.ftab[i].entry > themoduledata.ftab[i+1].entry {
}
}
- // The ftab ends with a half functab consisting only of
- // 'entry', followed by a uint32 giving the pcln-relative
- // offset of the file table.
- sp = (*sliceStruct)(unsafe.Pointer(&themoduledata.filetab))
- end := unsafe.Pointer(&themoduledata.ftab[nftab].funcoff) // just beyond ftab
- fileoffset := *(*uint32)(end)
- sp.array = unsafe.Pointer(&themoduledata.pclntable[fileoffset])
- // length is in first element of array.
- // set len to 1 so we can get first element.
- sp.len = 1
- sp.cap = 1
- sp.len = int(themoduledata.filetab[0])
- sp.cap = sp.len
-
- themoduledata.minpc = themoduledata.ftab[0].entry
- themoduledata.maxpc = themoduledata.ftab[nftab].entry
+ if themoduledata.minpc != themoduledata.ftab[0].entry ||
+ themoduledata.maxpc != themoduledata.ftab[nftab].entry {
+ throw("minpc or maxpc invalid")
+ }
}
// FuncForPC returns a *Func describing the function that contains the