]> Cypherpunks repositories - gostls13.git/commitdiff
runtime, cmd/internal/ld: change runtime to use a single linker symbol
authorMichael Hudson-Doyle <michael.hudson@canonical.com>
Wed, 11 Mar 2015 23:22:18 +0000 (12:22 +1300)
committerIan Lance Taylor <iant@golang.org>
Tue, 31 Mar 2015 22:45:07 +0000 (22:45 +0000)
In preparation for being able to run a go program that has code
in several objects, this changes from having several linker
symbols used by the runtime into having one linker symbol that
points at a structure containing the needed data.  Multiple
object support will construct a linked list of such structures.

A follow up will initialize the slices in the themoduledata
structure directly from the linker but I was aiming for a minimal
diff for now.

Change-Id: I613cce35309801cf265a1d5ae5aaca8d689c5cbf
Reviewed-on: https://go-review.googlesource.com/7441
Reviewed-by: Ian Lance Taylor <iant@golang.org>
15 files changed:
src/cmd/internal/ld/symtab.go
src/runtime/heapdump.go
src/runtime/malloc.go
src/runtime/mbarrier.go
src/runtime/mbitmap.go
src/runtime/mem_plan9.go
src/runtime/mfinal.go
src/runtime/mgc.go
src/runtime/mgcmark.go
src/runtime/os1_windows_386.go
src/runtime/os1_windows_amd64.go
src/runtime/proc1.go
src/runtime/race1.go
src/runtime/runtime1.go
src/runtime/symtab.go

index e165c8c855d6f0b2fd38f98a801a50c77f1b363d..6001ace01677560da54f85054b5814d386555284 100644 (file)
@@ -395,4 +395,38 @@ func symtab() {
                        liveness += (s.Size + int64(s.Align) - 1) &^ (int64(s.Align) - 1)
                }
        }
+
+       // 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.
+       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
+       Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.pclntab", 0))
+       Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.epclntab", 0))
+       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
+       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.enoptrdata", 0))
+       Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.data", 0))
+       Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.edata", 0))
+       Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.bss", 0))
+       Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.ebss", 0))
+       Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.noptrbss", 0))
+       Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.enoptrbss", 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))
+       Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.typelink", 0))
+       Addaddr(Ctxt, moduledata, Linklookup(Ctxt, "runtime.etypelink", 0))
 }
index f5770958fdac61dcadb1f92b715d0afd4316d92f..090a4904492aaaf9f33dcc3119eba89f73b2d052 100644 (file)
@@ -432,17 +432,17 @@ func finq_callback(fn *funcval, obj unsafe.Pointer, nret uintptr, fint *_type, o
 
 func dumproots() {
        // data segment
-       dumpbvtypes(&gcdatamask, unsafe.Pointer(&data))
+       dumpbvtypes(&gcdatamask, unsafe.Pointer(themoduledata.data))
        dumpint(tagData)
-       dumpint(uint64(uintptr(unsafe.Pointer(&data))))
-       dumpmemrange(unsafe.Pointer(&data), uintptr(unsafe.Pointer(&edata))-uintptr(unsafe.Pointer(&data)))
+       dumpint(uint64(themoduledata.data))
+       dumpmemrange(unsafe.Pointer(themoduledata.data), themoduledata.edata-themoduledata.data)
        dumpfields(gcdatamask)
 
        // bss segment
-       dumpbvtypes(&gcbssmask, unsafe.Pointer(&bss))
+       dumpbvtypes(&gcbssmask, unsafe.Pointer(themoduledata.bss))
        dumpint(tagBSS)
-       dumpint(uint64(uintptr(unsafe.Pointer(&bss))))
-       dumpmemrange(unsafe.Pointer(&bss), uintptr(unsafe.Pointer(&ebss))-uintptr(unsafe.Pointer(&bss)))
+       dumpint(uint64(themoduledata.bss))
+       dumpmemrange(unsafe.Pointer(themoduledata.bss), themoduledata.ebss-themoduledata.bss)
        dumpfields(gcbssmask)
 
        // MSpan.types
index 11d6f94e54266a227b2749fe60330f17f48093fb..fde58e2d0cf71c0d372af615b8f0e0a2aeb34230 100644 (file)
@@ -322,7 +322,7 @@ func mallocinit() {
                        // So adjust it upward a little bit ourselves: 1/4 MB to get
                        // away from the running binary image and then round up
                        // to a MB boundary.
-                       p = round(uintptr(unsafe.Pointer(&end))+(1<<18), 1<<20)
+                       p = round(themoduledata.end+(1<<18), 1<<20)
                        pSize = bitmapSize + spansSize + arenaSize + _PageSize
                        p = uintptr(sysReserve(unsafe.Pointer(p), pSize, &reserved))
                        if p != 0 {
index a64bd12815b873c7adf32b1eae10b748b9b30901..e6183e74a83e575bed4f39030cacfeb4ceaf695d 100644 (file)
@@ -428,29 +428,29 @@ func wbshadowinit() {
        mheap_.shadow_reserved = reserved
        start := ^uintptr(0)
        end := uintptr(0)
-       if start > uintptr(unsafe.Pointer(&noptrdata)) {
-               start = uintptr(unsafe.Pointer(&noptrdata))
+       if start > themoduledata.noptrdata {
+               start = themoduledata.noptrdata
        }
-       if start > uintptr(unsafe.Pointer(&data)) {
-               start = uintptr(unsafe.Pointer(&data))
+       if start > themoduledata.data {
+               start = themoduledata.data
        }
-       if start > uintptr(unsafe.Pointer(&noptrbss)) {
-               start = uintptr(unsafe.Pointer(&noptrbss))
+       if start > themoduledata.noptrbss {
+               start = themoduledata.noptrbss
        }
-       if start > uintptr(unsafe.Pointer(&bss)) {
-               start = uintptr(unsafe.Pointer(&bss))
+       if start > themoduledata.bss {
+               start = themoduledata.bss
        }
-       if end < uintptr(unsafe.Pointer(&enoptrdata)) {
-               end = uintptr(unsafe.Pointer(&enoptrdata))
+       if end < themoduledata.enoptrdata {
+               end = themoduledata.enoptrdata
        }
-       if end < uintptr(unsafe.Pointer(&edata)) {
-               end = uintptr(unsafe.Pointer(&edata))
+       if end < themoduledata.edata {
+               end = themoduledata.edata
        }
-       if end < uintptr(unsafe.Pointer(&enoptrbss)) {
-               end = uintptr(unsafe.Pointer(&enoptrbss))
+       if end < themoduledata.enoptrbss {
+               end = themoduledata.enoptrbss
        }
-       if end < uintptr(unsafe.Pointer(&ebss)) {
-               end = uintptr(unsafe.Pointer(&ebss))
+       if end < themoduledata.ebss {
+               end = themoduledata.ebss
        }
        start &^= _PhysPageSize - 1
        end = round(end, _PhysPageSize)
index 7dd3637665f6e22d40970cdc3090b80cfb2ccb25..ebee7429b19198e748dd4352f4fdf337a288da50 100644 (file)
@@ -747,12 +747,12 @@ func getgcmask(p unsafe.Pointer, t *_type, mask **byte, len *uintptr) {
        const typeBitsPerByte = 8 / typeBitsWidth
 
        // data
-       if uintptr(unsafe.Pointer(&data)) <= uintptr(p) && uintptr(p) < uintptr(unsafe.Pointer(&edata)) {
+       if themoduledata.data <= uintptr(p) && uintptr(p) < themoduledata.edata {
                n := (*ptrtype)(unsafe.Pointer(t)).elem.size
                *len = n / ptrSize
                *mask = &make([]byte, *len)[0]
                for i := uintptr(0); i < n; i += ptrSize {
-                       off := (uintptr(p) + i - uintptr(unsafe.Pointer(&data))) / ptrSize
+                       off := (uintptr(p) + i - themoduledata.data) / ptrSize
                        bits := (*(*byte)(add(unsafe.Pointer(gcdatamask.bytedata), off/typeBitsPerByte)) >> ((off % typeBitsPerByte) * typeBitsWidth)) & typeMask
                        *(*byte)(add(unsafe.Pointer(*mask), i/ptrSize)) = bits
                }
@@ -760,12 +760,12 @@ func getgcmask(p unsafe.Pointer, t *_type, mask **byte, len *uintptr) {
        }
 
        // bss
-       if uintptr(unsafe.Pointer(&bss)) <= uintptr(p) && uintptr(p) < uintptr(unsafe.Pointer(&ebss)) {
+       if themoduledata.bss <= uintptr(p) && uintptr(p) < themoduledata.ebss {
                n := (*ptrtype)(unsafe.Pointer(t)).elem.size
                *len = n / ptrSize
                *mask = &make([]byte, *len)[0]
                for i := uintptr(0); i < n; i += ptrSize {
-                       off := (uintptr(p) + i - uintptr(unsafe.Pointer(&bss))) / ptrSize
+                       off := (uintptr(p) + i - themoduledata.bss) / ptrSize
                        bits := (*(*byte)(add(unsafe.Pointer(gcbssmask.bytedata), off/typeBitsPerByte)) >> ((off % typeBitsPerByte) * typeBitsWidth)) & typeMask
                        *(*byte)(add(unsafe.Pointer(*mask), i/ptrSize)) = bits
                }
index bf7d23881f974d0d951ab00c051a562f7d735223..62c6a6f7de5dd3a075c08b6bc15a8e919e342fbc 100644 (file)
@@ -116,7 +116,7 @@ func memRound(p uintptr) uintptr {
 }
 
 func initBloc() {
-       bloc = memRound(uintptr(unsafe.Pointer(&end)))
+       bloc = memRound(themoduledata.end)
 }
 
 func sbrk(n uintptr) unsafe.Pointer {
index 55ba06d4b00adb37cfa8febb5ff9f479d92ffa31..2de75656e5f19cc829478b706025ba7d7daad35d 100644 (file)
@@ -289,10 +289,10 @@ func SetFinalizer(obj interface{}, finalizer interface{}) {
                // The relevant segments are: noptrdata, data, bss, noptrbss.
                // We cannot assume they are in any order or even contiguous,
                // due to external linking.
-               if uintptr(unsafe.Pointer(&noptrdata)) <= uintptr(e.data) && uintptr(e.data) < uintptr(unsafe.Pointer(&enoptrdata)) ||
-                       uintptr(unsafe.Pointer(&data)) <= uintptr(e.data) && uintptr(e.data) < uintptr(unsafe.Pointer(&edata)) ||
-                       uintptr(unsafe.Pointer(&bss)) <= uintptr(e.data) && uintptr(e.data) < uintptr(unsafe.Pointer(&ebss)) ||
-                       uintptr(unsafe.Pointer(&noptrbss)) <= uintptr(e.data) && uintptr(e.data) < uintptr(unsafe.Pointer(&enoptrbss)) {
+               if themoduledata.noptrdata <= uintptr(e.data) && uintptr(e.data) < themoduledata.enoptrdata ||
+                       themoduledata.data <= uintptr(e.data) && uintptr(e.data) < themoduledata.edata ||
+                       themoduledata.bss <= uintptr(e.data) && uintptr(e.data) < themoduledata.ebss ||
+                       themoduledata.noptrbss <= uintptr(e.data) && uintptr(e.data) < themoduledata.enoptrbss {
                        return
                }
                throw("runtime.SetFinalizer: pointer not in allocated block")
index 8eba5a8bc2dfa8024906e1e405fb1323a5c6ffd0..89f3fb534086d98e2f78519d25387a15219af8c9 100644 (file)
@@ -130,9 +130,6 @@ const (
        _RootCount       = 5
 )
 
-// linker-provided
-var data, edata, bss, ebss, gcdata, gcbss, noptrdata, enoptrdata, noptrbss, enoptrbss, end struct{}
-
 //go:linkname weak_cgo_allocate go.weak.runtime._cgo_allocate_internal
 var weak_cgo_allocate byte
 
@@ -160,8 +157,8 @@ func gcinit() {
 
        work.markfor = parforalloc(_MaxGcproc)
        gcpercent = readgogc()
-       gcdatamask = unrollglobgcprog((*byte)(unsafe.Pointer(&gcdata)), uintptr(unsafe.Pointer(&edata))-uintptr(unsafe.Pointer(&data)))
-       gcbssmask = unrollglobgcprog((*byte)(unsafe.Pointer(&gcbss)), uintptr(unsafe.Pointer(&ebss))-uintptr(unsafe.Pointer(&bss)))
+       gcdatamask = unrollglobgcprog((*byte)(unsafe.Pointer(themoduledata.gcdata)), themoduledata.edata-themoduledata.data)
+       gcbssmask = unrollglobgcprog((*byte)(unsafe.Pointer(themoduledata.gcbss)), themoduledata.ebss-themoduledata.bss)
        memstats.next_gc = heapminimum
 }
 
index bdb5888a28fa83e56248aefedb91f9a2b73f3890..3a9679e43a6c15e423578d84b4a9921788ac878e 100644 (file)
@@ -60,10 +60,10 @@ func markroot(desc *parfor, i uint32) {
        // Note: if you add a case here, please also update heapdump.go:dumproots.
        switch i {
        case _RootData:
-               scanblock(uintptr(unsafe.Pointer(&data)), uintptr(unsafe.Pointer(&edata))-uintptr(unsafe.Pointer(&data)), gcdatamask.bytedata, &gcw)
+               scanblock(themoduledata.data, themoduledata.edata-themoduledata.data, gcdatamask.bytedata, &gcw)
 
        case _RootBss:
-               scanblock(uintptr(unsafe.Pointer(&bss)), uintptr(unsafe.Pointer(&ebss))-uintptr(unsafe.Pointer(&bss)), gcbssmask.bytedata, &gcw)
+               scanblock(themoduledata.bss, themoduledata.ebss-themoduledata.bss, gcbssmask.bytedata, &gcw)
 
        case _RootFinalizers:
                for fb := allfin; fb != nil; fb = fb.alllink {
index f105539659fd82301fa80d0c05d6866a7b2c13d5..e5fe7486cb26b94d0ce9feeebee5a9eb8a51277f 100644 (file)
@@ -8,8 +8,6 @@ import (
        "unsafe"
 )
 
-var text struct{}
-
 func dumpregs(r *context) {
        print("eax     ", hex(r.eax), "\n")
        print("ebx     ", hex(r.ebx), "\n")
@@ -29,7 +27,7 @@ func dumpregs(r *context) {
 func isgoexception(info *exceptionrecord, r *context) bool {
        // Only handle exception if executing instructions in Go binary
        // (not Windows library code).
-       if r.eip < uint32(uintptr(unsafe.Pointer(&text))) || uint32(uintptr(unsafe.Pointer(&etext))) < r.eip {
+       if r.eip < uint32(themoduledata.text) || uint32(themoduledata.etext) < r.eip {
                return false
        }
 
index 1b6b99988d9d617392406229d03835ee8ed33c15..37a97b73829a0e2989de06bfe84c00d46b4ae8d3 100644 (file)
@@ -8,8 +8,6 @@ import (
        "unsafe"
 )
 
-var text struct{}
-
 func dumpregs(r *context) {
        print("rax     ", hex(r.rax), "\n")
        print("rbx     ", hex(r.rbx), "\n")
@@ -36,7 +34,7 @@ func dumpregs(r *context) {
 func isgoexception(info *exceptionrecord, r *context) bool {
        // Only handle exception if executing instructions in Go binary
        // (not Windows library code).
-       if r.rip < uint64(uintptr(unsafe.Pointer(&text))) || uint64(uintptr(unsafe.Pointer(&etext))) < r.rip {
+       if r.rip < uint64(themoduledata.text) || uint64(themoduledata.etext) < r.rip {
                return false
        }
 
index 30d6c7b9c65191dcaf8de915294d862c9f279c89..7fa519dd7020799733f27bda1be3defd0cc1aae3 100644 (file)
@@ -2293,8 +2293,6 @@ func _System()       { _System() }
 func _ExternalCode() { _ExternalCode() }
 func _GC()           { _GC() }
 
-var etext struct{}
-
 // Called if we receive a SIGPROF signal.
 func sigprof(pc, sp, lr uintptr, gp *g, mp *m) {
        if prof.hz == 0 {
@@ -2408,7 +2406,7 @@ func sigprof(pc, sp, lr uintptr, gp *g, mp *m) {
                        // If all of the above has failed, account it against abstract "System" or "GC".
                        n = 2
                        // "ExternalCode" is better than "etext".
-                       if pc > uintptr(unsafe.Pointer(&etext)) {
+                       if pc > themoduledata.etext {
                                pc = funcPC(_ExternalCode) + _PCQuantum
                        }
                        stk[0] = pc
index 4c14d84746eda46471580e227606d16b5bcdecee..18ecc88a5fb9990d937c8bd45950bab45ba2047c 100644 (file)
@@ -119,29 +119,29 @@ func raceinit() uintptr {
        // Round data segment to page boundaries, because it's used in mmap().
        start := ^uintptr(0)
        end := uintptr(0)
-       if start > uintptr(unsafe.Pointer(&noptrdata)) {
-               start = uintptr(unsafe.Pointer(&noptrdata))
+       if start > themoduledata.noptrdata {
+               start = themoduledata.noptrdata
        }
-       if start > uintptr(unsafe.Pointer(&data)) {
-               start = uintptr(unsafe.Pointer(&data))
+       if start > themoduledata.data {
+               start = themoduledata.data
        }
-       if start > uintptr(unsafe.Pointer(&noptrbss)) {
-               start = uintptr(unsafe.Pointer(&noptrbss))
+       if start > themoduledata.noptrbss {
+               start = themoduledata.noptrbss
        }
-       if start > uintptr(unsafe.Pointer(&bss)) {
-               start = uintptr(unsafe.Pointer(&bss))
+       if start > themoduledata.bss {
+               start = themoduledata.bss
        }
-       if end < uintptr(unsafe.Pointer(&enoptrdata)) {
-               end = uintptr(unsafe.Pointer(&enoptrdata))
+       if end < themoduledata.enoptrdata {
+               end = themoduledata.enoptrdata
        }
-       if end < uintptr(unsafe.Pointer(&edata)) {
-               end = uintptr(unsafe.Pointer(&edata))
+       if end < themoduledata.edata {
+               end = themoduledata.edata
        }
-       if end < uintptr(unsafe.Pointer(&enoptrbss)) {
-               end = uintptr(unsafe.Pointer(&enoptrbss))
+       if end < themoduledata.enoptrbss {
+               end = themoduledata.enoptrbss
        }
-       if end < uintptr(unsafe.Pointer(&ebss)) {
-               end = uintptr(unsafe.Pointer(&ebss))
+       if end < themoduledata.ebss {
+               end = themoduledata.ebss
        }
        size := round(end-start, _PageSize)
        racecall(&__tsan_map_shadow, start, size, 0, 0)
index ac9042c79289a99d121d0273e5a13d88c8d248c6..072a58552e6dc5cd6b3b3c55af21a924eea7ff2e 100644 (file)
@@ -424,15 +424,13 @@ func gomcache() *mcache {
        return getg().m.mcache
 }
 
-var typelink, etypelink [0]byte
-
 //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(&typelink))
-       sp.len = uint((uintptr(unsafe.Pointer(&etypelink)) - uintptr(unsafe.Pointer(&typelink))) / unsafe.Sizeof(ret[0]))
+       sp.array = (*byte)(unsafe.Pointer(themoduledata.typelink))
+       sp.len = uint((themoduledata.etypelink - themoduledata.typelink) / unsafe.Sizeof(ret[0]))
        sp.cap = sp.len
        return ret
 }
index 4f3111d551202d117e5eca5132512a58763fa15c..689a3361a8bce10b1dd688b475d2e968442b10a5 100644 (file)
@@ -29,15 +29,27 @@ const (
        _ArgsSizeUnknown            = -0x80000000
 )
 
-var (
-       pclntable []byte
-       ftab      []functab
-       filetab   []uint32
-
-       pclntab, epclntab, findfunctab struct{} // linker symbols
+// moduledata records information about the layout of the executable
+// 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
+
+       text, etext           uintptr
+       noptrdata, enoptrdata uintptr
+       data, edata           uintptr
+       bss, ebss             uintptr
+       noptrbss, enoptrbss   uintptr
+       end, gcdata, gcbss    uintptr
+
+       typelink, etypelink uintptr
+}
 
-       minpc, maxpc uintptr
-)
+var themoduledata moduledata // linker symbol
 
 type functab struct {
        entry   uintptr
@@ -64,38 +76,38 @@ func symtabinit() {
        // 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(&pclntab))
-       pcln32 := (*[2]uint32)(unsafe.Pointer(&pclntab))
+       pcln := (*[8]byte)(unsafe.Pointer(themoduledata.pclntab))
+       pcln32 := (*[2]uint32)(unsafe.Pointer(themoduledata.pclntab))
        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(&pclntable))
-       sp.array = unsafe.Pointer(&pclntab)
-       sp.len = int(uintptr(unsafe.Pointer(&epclntab)) - uintptr(unsafe.Pointer(&pclntab)))
+       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(&ftab))
+       sp = (*sliceStruct)(unsafe.Pointer(&themoduledata.ftab))
        sp.array = p
        sp.len = nftab + 1
        sp.cap = sp.len
        for i := 0; i < nftab; i++ {
                // NOTE: ftab[nftab].entry is legal; it is the address beyond the final function.
-               if ftab[i].entry > ftab[i+1].entry {
-                       f1 := (*_func)(unsafe.Pointer(&pclntable[ftab[i].funcoff]))
-                       f2 := (*_func)(unsafe.Pointer(&pclntable[ftab[i+1].funcoff]))
+               if themoduledata.ftab[i].entry > themoduledata.ftab[i+1].entry {
+                       f1 := (*_func)(unsafe.Pointer(&themoduledata.pclntable[themoduledata.ftab[i].funcoff]))
+                       f2 := (*_func)(unsafe.Pointer(&themoduledata.pclntable[themoduledata.ftab[i+1].funcoff]))
                        f2name := "end"
                        if i+1 < nftab {
                                f2name = funcname(f2)
                        }
-                       println("function symbol table not sorted by program counter:", hex(ftab[i].entry), funcname(f1), ">", hex(ftab[i+1].entry), f2name)
+                       println("function symbol table not sorted by program counter:", hex(themoduledata.ftab[i].entry), funcname(f1), ">", hex(themoduledata.ftab[i+1].entry), f2name)
                        for j := 0; j <= i; j++ {
-                               print("\t", hex(ftab[j].entry), " ", funcname((*_func)(unsafe.Pointer(&pclntable[ftab[j].funcoff]))), "\n")
+                               print("\t", hex(themoduledata.ftab[j].entry), " ", funcname((*_func)(unsafe.Pointer(&themoduledata.pclntable[themoduledata.ftab[j].funcoff]))), "\n")
                        }
                        throw("invalid runtime symbol table")
                }
@@ -104,19 +116,19 @@ 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(&filetab))
-       end := unsafe.Pointer(&ftab[nftab].funcoff) // just beyond ftab
+       sp = (*sliceStruct)(unsafe.Pointer(&themoduledata.filetab))
+       end := unsafe.Pointer(&themoduledata.ftab[nftab].funcoff) // just beyond ftab
        fileoffset := *(*uint32)(end)
-       sp.array = unsafe.Pointer(&pclntable[fileoffset])
+       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(filetab[0])
+       sp.len = int(themoduledata.filetab[0])
        sp.cap = sp.len
 
-       minpc = ftab[0].entry
-       maxpc = ftab[nftab].entry
+       themoduledata.minpc = themoduledata.ftab[0].entry
+       themoduledata.maxpc = themoduledata.ftab[nftab].entry
 }
 
 // FuncForPC returns a *Func describing the function that contains the
@@ -147,33 +159,33 @@ func (f *Func) FileLine(pc uintptr) (file string, line int) {
 }
 
 func findfunc(pc uintptr) *_func {
-       if pc < minpc || pc >= maxpc {
+       if pc < themoduledata.minpc || pc >= themoduledata.maxpc {
                return nil
        }
        const nsub = uintptr(len(findfuncbucket{}.subbuckets))
 
-       x := pc - minpc
+       x := pc - themoduledata.minpc
        b := x / pcbucketsize
        i := x % pcbucketsize / (pcbucketsize / nsub)
 
-       ffb := (*findfuncbucket)(add(unsafe.Pointer(&findfunctab), b*unsafe.Sizeof(findfuncbucket{})))
+       ffb := (*findfuncbucket)(add(unsafe.Pointer(themoduledata.findfunctab), b*unsafe.Sizeof(findfuncbucket{})))
        idx := ffb.idx + uint32(ffb.subbuckets[i])
-       if pc < ftab[idx].entry {
+       if pc < themoduledata.ftab[idx].entry {
                throw("findfunc: bad findfunctab entry")
        }
 
        // linear search to find func with pc >= entry.
-       for ftab[idx+1].entry <= pc {
+       for themoduledata.ftab[idx+1].entry <= pc {
                idx++
        }
-       return (*_func)(unsafe.Pointer(&pclntable[ftab[idx].funcoff]))
+       return (*_func)(unsafe.Pointer(&themoduledata.pclntable[themoduledata.ftab[idx].funcoff]))
 }
 
 func pcvalue(f *_func, off int32, targetpc uintptr, strict bool) int32 {
        if off == 0 {
                return -1
        }
-       p := pclntable[off:]
+       p := themoduledata.pclntable[off:]
        pc := f.entry
        val := int32(-1)
        for {
@@ -195,7 +207,7 @@ func pcvalue(f *_func, off int32, targetpc uintptr, strict bool) int32 {
 
        print("runtime: invalid pc-encoded table f=", funcname(f), " pc=", hex(pc), " targetpc=", hex(targetpc), " tab=", p, "\n")
 
-       p = pclntable[off:]
+       p = themoduledata.pclntable[off:]
        pc = f.entry
        val = -1
        for {
@@ -215,7 +227,7 @@ func cfuncname(f *_func) *byte {
        if f == nil || f.nameoff == 0 {
                return nil
        }
-       return (*byte)(unsafe.Pointer(&pclntable[f.nameoff]))
+       return (*byte)(unsafe.Pointer(&themoduledata.pclntable[f.nameoff]))
 }
 
 func funcname(f *_func) string {
@@ -225,11 +237,11 @@ func funcname(f *_func) string {
 func funcline1(f *_func, targetpc uintptr, strict bool) (file string, line int32) {
        fileno := int(pcvalue(f, f.pcfile, targetpc, strict))
        line = pcvalue(f, f.pcln, targetpc, strict)
-       if fileno == -1 || line == -1 || fileno >= len(filetab) {
+       if fileno == -1 || line == -1 || fileno >= len(themoduledata.filetab) {
                // print("looking for ", hex(targetpc), " in ", funcname(f), " got file=", fileno, " line=", lineno, "\n")
                return "?", 0
        }
-       file = gostringnocopy(&pclntable[filetab[fileno]])
+       file = gostringnocopy(&themoduledata.pclntable[themoduledata.filetab[fileno]])
        return
 }