From 3a84e3305b7edebf50f2cc3067aa009f9934488c Mon Sep 17 00:00:00 2001 From: Michael Hudson-Doyle Date: Mon, 16 Mar 2015 11:53:08 +1300 Subject: [PATCH] runtime, cmd/internal/ld: initialize themoduledata slices directly This CL is quite conservative in some ways. It continues to define symbols that have no real purpose (e.g. epclntab). These could be deleted if there is no concern that external tools might look for them. It would also now be possible to make some changes to the pcln data but I get the impression that would definitely require some thought and discussion. Change-Id: Ib33cde07e4ec38ecc1d6c319a10138c9347933a3 Reviewed-on: https://go-review.googlesource.com/7616 Run-TryBot: Ian Lance Taylor TryBot-Result: Gobot Gobot Reviewed-by: Ian Lance Taylor --- src/cmd/internal/ld/data.go | 4 +++ src/cmd/internal/ld/pcln.go | 15 +++++++++++ src/cmd/internal/ld/symtab.go | 33 ++++++++++++++++------- src/runtime/proc1.go | 2 +- src/runtime/runtime1.go | 7 +---- src/runtime/symtab.go | 51 ++++++++++------------------------- 6 files changed, 58 insertions(+), 54 deletions(-) diff --git a/src/cmd/internal/ld/data.go b/src/cmd/internal/ld/data.go index bc2021aaf0..e67451419f 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 0250ca0eb8..65ca0c32ea 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 c5b32fd21f..4e1bfc685d 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 b8ea36c5ba..772fa0962a 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 072a58552e..5fddc582e9 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 689a3361a8..8ee80c8eed 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