diff --git a/src/cmd/internal/ld/data.go b/src/cmd/internal/ld/data.go index bc2021aaf07..e67451419f7 100644 --- a/src/cmd/internal/ld/data.go +++ b/src/cmd/internal/ld/data.go @@ -102,6 +102,10 @@ func Adduint64(ctxt *Link, s *LSym, v uint64) int64 { 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) } diff --git a/src/cmd/internal/ld/pcln.go b/src/cmd/internal/ld/pcln.go index 0250ca0eb82..65ca0c32eab 100644 --- a/src/cmd/internal/ld/pcln.go +++ b/src/cmd/internal/ld/pcln.go @@ -202,6 +202,13 @@ func container(s *LSym) int { 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) @@ -222,11 +229,13 @@ func pclntab() { } } + 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 @@ -246,6 +255,10 @@ func pclntab() { pcln = &pclntab_zpcln } + if pclntabFirstFunc == nil { + pclntabFirstFunc = Ctxt.Cursym + } + funcstart = int32(len(ftab.P)) funcstart += int32(-len(ftab.P)) & (int32(Thearch.Ptrsize) - 1) @@ -330,6 +343,7 @@ func pclntab() { 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) @@ -337,6 +351,7 @@ func pclntab() { 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) diff --git a/src/cmd/internal/ld/symtab.go b/src/cmd/internal/ld/symtab.go index c5b32fd21f9..4e1bfc685df 100644 --- a/src/cmd/internal/ld/symtab.go +++ b/src/cmd/internal/ld/symtab.go @@ -348,6 +348,8 @@ func symtab() { 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. @@ -363,6 +365,7 @@ func symtab() { } if strings.HasPrefix(s.Name, "go.typelink.") { + ntypelinks++ s.Type = STYPELINK s.Hide = 1 s.Outer = symtypelink @@ -392,21 +395,29 @@ func symtab() { // 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)) @@ -420,6 +431,8 @@ func symtab() { 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)) } diff --git a/src/runtime/proc1.go b/src/runtime/proc1.go index b8ea36c5ba9..772fa0962af 100644 --- a/src/runtime/proc1.go +++ b/src/runtime/proc1.go @@ -51,7 +51,7 @@ func schedinit() { framepointer_enabled = haveexperiment("framepointer") tracebackinit() - symtabinit() + symtabverify() stackinit() mallocinit() mcommoninit(_g_.m) diff --git a/src/runtime/runtime1.go b/src/runtime/runtime1.go index 072a58552e6..5fddc582e92 100644 --- a/src/runtime/runtime1.go +++ b/src/runtime/runtime1.go @@ -427,12 +427,7 @@ func gomcache() *mcache { //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 diff --git a/src/runtime/symtab.go b/src/runtime/symtab.go index 689a3361a8b..8ee80c8eeda 100644 --- a/src/runtime/symtab.go +++ b/src/runtime/symtab.go @@ -33,11 +33,11 @@ const ( // 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 @@ -46,7 +46,7 @@ type moduledata struct { noptrbss, enoptrbss uintptr end, gcdata, gcbss uintptr - typelink, etypelink uintptr + typelinks []*_type } var themoduledata moduledata // linker symbol @@ -72,30 +72,19 @@ type findfuncbucket struct { 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 { @@ -113,22 +102,10 @@ func symtabinit() { } } - // 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