Commit 67426a8a authored by Michael Hudson-Doyle's avatar Michael Hudson-Doyle Committed by Ian Lance Taylor

runtime, cmd/internal/ld: change runtime to use a single linker symbol

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/7441Reviewed-by: default avatarIan Lance Taylor <iant@golang.org>
parent 0de359da
...@@ -395,4 +395,38 @@ func symtab() { ...@@ -395,4 +395,38 @@ func symtab() {
liveness += (s.Size + int64(s.Align) - 1) &^ (int64(s.Align) - 1) 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))
} }
...@@ -432,17 +432,17 @@ func finq_callback(fn *funcval, obj unsafe.Pointer, nret uintptr, fint *_type, o ...@@ -432,17 +432,17 @@ func finq_callback(fn *funcval, obj unsafe.Pointer, nret uintptr, fint *_type, o
func dumproots() { func dumproots() {
// data segment // data segment
dumpbvtypes(&gcdatamask, unsafe.Pointer(&data)) dumpbvtypes(&gcdatamask, unsafe.Pointer(themoduledata.data))
dumpint(tagData) dumpint(tagData)
dumpint(uint64(uintptr(unsafe.Pointer(&data)))) dumpint(uint64(themoduledata.data))
dumpmemrange(unsafe.Pointer(&data), uintptr(unsafe.Pointer(&edata))-uintptr(unsafe.Pointer(&data))) dumpmemrange(unsafe.Pointer(themoduledata.data), themoduledata.edata-themoduledata.data)
dumpfields(gcdatamask) dumpfields(gcdatamask)
// bss segment // bss segment
dumpbvtypes(&gcbssmask, unsafe.Pointer(&bss)) dumpbvtypes(&gcbssmask, unsafe.Pointer(themoduledata.bss))
dumpint(tagBSS) dumpint(tagBSS)
dumpint(uint64(uintptr(unsafe.Pointer(&bss)))) dumpint(uint64(themoduledata.bss))
dumpmemrange(unsafe.Pointer(&bss), uintptr(unsafe.Pointer(&ebss))-uintptr(unsafe.Pointer(&bss))) dumpmemrange(unsafe.Pointer(themoduledata.bss), themoduledata.ebss-themoduledata.bss)
dumpfields(gcbssmask) dumpfields(gcbssmask)
// MSpan.types // MSpan.types
......
...@@ -322,7 +322,7 @@ func mallocinit() { ...@@ -322,7 +322,7 @@ func mallocinit() {
// So adjust it upward a little bit ourselves: 1/4 MB to get // So adjust it upward a little bit ourselves: 1/4 MB to get
// away from the running binary image and then round up // away from the running binary image and then round up
// to a MB boundary. // 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 pSize = bitmapSize + spansSize + arenaSize + _PageSize
p = uintptr(sysReserve(unsafe.Pointer(p), pSize, &reserved)) p = uintptr(sysReserve(unsafe.Pointer(p), pSize, &reserved))
if p != 0 { if p != 0 {
......
...@@ -428,29 +428,29 @@ func wbshadowinit() { ...@@ -428,29 +428,29 @@ func wbshadowinit() {
mheap_.shadow_reserved = reserved mheap_.shadow_reserved = reserved
start := ^uintptr(0) start := ^uintptr(0)
end := uintptr(0) end := uintptr(0)
if start > uintptr(unsafe.Pointer(&noptrdata)) { if start > themoduledata.noptrdata {
start = uintptr(unsafe.Pointer(&noptrdata)) start = themoduledata.noptrdata
} }
if start > uintptr(unsafe.Pointer(&data)) { if start > themoduledata.data {
start = uintptr(unsafe.Pointer(&data)) start = themoduledata.data
} }
if start > uintptr(unsafe.Pointer(&noptrbss)) { if start > themoduledata.noptrbss {
start = uintptr(unsafe.Pointer(&noptrbss)) start = themoduledata.noptrbss
} }
if start > uintptr(unsafe.Pointer(&bss)) { if start > themoduledata.bss {
start = uintptr(unsafe.Pointer(&bss)) start = themoduledata.bss
} }
if end < uintptr(unsafe.Pointer(&enoptrdata)) { if end < themoduledata.enoptrdata {
end = uintptr(unsafe.Pointer(&enoptrdata)) end = themoduledata.enoptrdata
} }
if end < uintptr(unsafe.Pointer(&edata)) { if end < themoduledata.edata {
end = uintptr(unsafe.Pointer(&edata)) end = themoduledata.edata
} }
if end < uintptr(unsafe.Pointer(&enoptrbss)) { if end < themoduledata.enoptrbss {
end = uintptr(unsafe.Pointer(&enoptrbss)) end = themoduledata.enoptrbss
} }
if end < uintptr(unsafe.Pointer(&ebss)) { if end < themoduledata.ebss {
end = uintptr(unsafe.Pointer(&ebss)) end = themoduledata.ebss
} }
start &^= _PhysPageSize - 1 start &^= _PhysPageSize - 1
end = round(end, _PhysPageSize) end = round(end, _PhysPageSize)
......
...@@ -747,12 +747,12 @@ func getgcmask(p unsafe.Pointer, t *_type, mask **byte, len *uintptr) { ...@@ -747,12 +747,12 @@ func getgcmask(p unsafe.Pointer, t *_type, mask **byte, len *uintptr) {
const typeBitsPerByte = 8 / typeBitsWidth const typeBitsPerByte = 8 / typeBitsWidth
// data // 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 n := (*ptrtype)(unsafe.Pointer(t)).elem.size
*len = n / ptrSize *len = n / ptrSize
*mask = &make([]byte, *len)[0] *mask = &make([]byte, *len)[0]
for i := uintptr(0); i < n; i += ptrSize { 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 bits := (*(*byte)(add(unsafe.Pointer(gcdatamask.bytedata), off/typeBitsPerByte)) >> ((off % typeBitsPerByte) * typeBitsWidth)) & typeMask
*(*byte)(add(unsafe.Pointer(*mask), i/ptrSize)) = bits *(*byte)(add(unsafe.Pointer(*mask), i/ptrSize)) = bits
} }
...@@ -760,12 +760,12 @@ func getgcmask(p unsafe.Pointer, t *_type, mask **byte, len *uintptr) { ...@@ -760,12 +760,12 @@ func getgcmask(p unsafe.Pointer, t *_type, mask **byte, len *uintptr) {
} }
// bss // 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 n := (*ptrtype)(unsafe.Pointer(t)).elem.size
*len = n / ptrSize *len = n / ptrSize
*mask = &make([]byte, *len)[0] *mask = &make([]byte, *len)[0]
for i := uintptr(0); i < n; i += ptrSize { 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 bits := (*(*byte)(add(unsafe.Pointer(gcbssmask.bytedata), off/typeBitsPerByte)) >> ((off % typeBitsPerByte) * typeBitsWidth)) & typeMask
*(*byte)(add(unsafe.Pointer(*mask), i/ptrSize)) = bits *(*byte)(add(unsafe.Pointer(*mask), i/ptrSize)) = bits
} }
......
...@@ -116,7 +116,7 @@ func memRound(p uintptr) uintptr { ...@@ -116,7 +116,7 @@ func memRound(p uintptr) uintptr {
} }
func initBloc() { func initBloc() {
bloc = memRound(uintptr(unsafe.Pointer(&end))) bloc = memRound(themoduledata.end)
} }
func sbrk(n uintptr) unsafe.Pointer { func sbrk(n uintptr) unsafe.Pointer {
......
...@@ -289,10 +289,10 @@ func SetFinalizer(obj interface{}, finalizer interface{}) { ...@@ -289,10 +289,10 @@ func SetFinalizer(obj interface{}, finalizer interface{}) {
// The relevant segments are: noptrdata, data, bss, noptrbss. // The relevant segments are: noptrdata, data, bss, noptrbss.
// We cannot assume they are in any order or even contiguous, // We cannot assume they are in any order or even contiguous,
// due to external linking. // due to external linking.
if uintptr(unsafe.Pointer(&noptrdata)) <= uintptr(e.data) && uintptr(e.data) < uintptr(unsafe.Pointer(&enoptrdata)) || if themoduledata.noptrdata <= uintptr(e.data) && uintptr(e.data) < themoduledata.enoptrdata ||
uintptr(unsafe.Pointer(&data)) <= uintptr(e.data) && uintptr(e.data) < uintptr(unsafe.Pointer(&edata)) || themoduledata.data <= uintptr(e.data) && uintptr(e.data) < themoduledata.edata ||
uintptr(unsafe.Pointer(&bss)) <= uintptr(e.data) && uintptr(e.data) < uintptr(unsafe.Pointer(&ebss)) || themoduledata.bss <= uintptr(e.data) && uintptr(e.data) < themoduledata.ebss ||
uintptr(unsafe.Pointer(&noptrbss)) <= uintptr(e.data) && uintptr(e.data) < uintptr(unsafe.Pointer(&enoptrbss)) { themoduledata.noptrbss <= uintptr(e.data) && uintptr(e.data) < themoduledata.enoptrbss {
return return
} }
throw("runtime.SetFinalizer: pointer not in allocated block") throw("runtime.SetFinalizer: pointer not in allocated block")
......
...@@ -130,9 +130,6 @@ const ( ...@@ -130,9 +130,6 @@ const (
_RootCount = 5 _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 //go:linkname weak_cgo_allocate go.weak.runtime._cgo_allocate_internal
var weak_cgo_allocate byte var weak_cgo_allocate byte
...@@ -160,8 +157,8 @@ func gcinit() { ...@@ -160,8 +157,8 @@ func gcinit() {
work.markfor = parforalloc(_MaxGcproc) work.markfor = parforalloc(_MaxGcproc)
gcpercent = readgogc() gcpercent = readgogc()
gcdatamask = unrollglobgcprog((*byte)(unsafe.Pointer(&gcdata)), uintptr(unsafe.Pointer(&edata))-uintptr(unsafe.Pointer(&data))) gcdatamask = unrollglobgcprog((*byte)(unsafe.Pointer(themoduledata.gcdata)), themoduledata.edata-themoduledata.data)
gcbssmask = unrollglobgcprog((*byte)(unsafe.Pointer(&gcbss)), uintptr(unsafe.Pointer(&ebss))-uintptr(unsafe.Pointer(&bss))) gcbssmask = unrollglobgcprog((*byte)(unsafe.Pointer(themoduledata.gcbss)), themoduledata.ebss-themoduledata.bss)
memstats.next_gc = heapminimum memstats.next_gc = heapminimum
} }
......
...@@ -60,10 +60,10 @@ func markroot(desc *parfor, i uint32) { ...@@ -60,10 +60,10 @@ func markroot(desc *parfor, i uint32) {
// Note: if you add a case here, please also update heapdump.go:dumproots. // Note: if you add a case here, please also update heapdump.go:dumproots.
switch i { switch i {
case _RootData: 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: 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: case _RootFinalizers:
for fb := allfin; fb != nil; fb = fb.alllink { for fb := allfin; fb != nil; fb = fb.alllink {
......
...@@ -8,8 +8,6 @@ import ( ...@@ -8,8 +8,6 @@ import (
"unsafe" "unsafe"
) )
var text struct{}
func dumpregs(r *context) { func dumpregs(r *context) {
print("eax ", hex(r.eax), "\n") print("eax ", hex(r.eax), "\n")
print("ebx ", hex(r.ebx), "\n") print("ebx ", hex(r.ebx), "\n")
...@@ -29,7 +27,7 @@ func dumpregs(r *context) { ...@@ -29,7 +27,7 @@ func dumpregs(r *context) {
func isgoexception(info *exceptionrecord, r *context) bool { func isgoexception(info *exceptionrecord, r *context) bool {
// Only handle exception if executing instructions in Go binary // Only handle exception if executing instructions in Go binary
// (not Windows library code). // (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 return false
} }
......
...@@ -8,8 +8,6 @@ import ( ...@@ -8,8 +8,6 @@ import (
"unsafe" "unsafe"
) )
var text struct{}
func dumpregs(r *context) { func dumpregs(r *context) {
print("rax ", hex(r.rax), "\n") print("rax ", hex(r.rax), "\n")
print("rbx ", hex(r.rbx), "\n") print("rbx ", hex(r.rbx), "\n")
...@@ -36,7 +34,7 @@ func dumpregs(r *context) { ...@@ -36,7 +34,7 @@ func dumpregs(r *context) {
func isgoexception(info *exceptionrecord, r *context) bool { func isgoexception(info *exceptionrecord, r *context) bool {
// Only handle exception if executing instructions in Go binary // Only handle exception if executing instructions in Go binary
// (not Windows library code). // (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 return false
} }
......
...@@ -2293,8 +2293,6 @@ func _System() { _System() } ...@@ -2293,8 +2293,6 @@ func _System() { _System() }
func _ExternalCode() { _ExternalCode() } func _ExternalCode() { _ExternalCode() }
func _GC() { _GC() } func _GC() { _GC() }
var etext struct{}
// Called if we receive a SIGPROF signal. // Called if we receive a SIGPROF signal.
func sigprof(pc, sp, lr uintptr, gp *g, mp *m) { func sigprof(pc, sp, lr uintptr, gp *g, mp *m) {
if prof.hz == 0 { if prof.hz == 0 {
...@@ -2408,7 +2406,7 @@ func sigprof(pc, sp, lr uintptr, gp *g, mp *m) { ...@@ -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". // If all of the above has failed, account it against abstract "System" or "GC".
n = 2 n = 2
// "ExternalCode" is better than "etext". // "ExternalCode" is better than "etext".
if pc > uintptr(unsafe.Pointer(&etext)) { if pc > themoduledata.etext {
pc = funcPC(_ExternalCode) + _PCQuantum pc = funcPC(_ExternalCode) + _PCQuantum
} }
stk[0] = pc stk[0] = pc
......
...@@ -119,29 +119,29 @@ func raceinit() uintptr { ...@@ -119,29 +119,29 @@ func raceinit() uintptr {
// Round data segment to page boundaries, because it's used in mmap(). // Round data segment to page boundaries, because it's used in mmap().
start := ^uintptr(0) start := ^uintptr(0)
end := uintptr(0) end := uintptr(0)
if start > uintptr(unsafe.Pointer(&noptrdata)) { if start > themoduledata.noptrdata {
start = uintptr(unsafe.Pointer(&noptrdata)) start = themoduledata.noptrdata
} }
if start > uintptr(unsafe.Pointer(&data)) { if start > themoduledata.data {
start = uintptr(unsafe.Pointer(&data)) start = themoduledata.data
} }
if start > uintptr(unsafe.Pointer(&noptrbss)) { if start > themoduledata.noptrbss {
start = uintptr(unsafe.Pointer(&noptrbss)) start = themoduledata.noptrbss
} }
if start > uintptr(unsafe.Pointer(&bss)) { if start > themoduledata.bss {
start = uintptr(unsafe.Pointer(&bss)) start = themoduledata.bss
} }
if end < uintptr(unsafe.Pointer(&enoptrdata)) { if end < themoduledata.enoptrdata {
end = uintptr(unsafe.Pointer(&enoptrdata)) end = themoduledata.enoptrdata
} }
if end < uintptr(unsafe.Pointer(&edata)) { if end < themoduledata.edata {
end = uintptr(unsafe.Pointer(&edata)) end = themoduledata.edata
} }
if end < uintptr(unsafe.Pointer(&enoptrbss)) { if end < themoduledata.enoptrbss {
end = uintptr(unsafe.Pointer(&enoptrbss)) end = themoduledata.enoptrbss
} }
if end < uintptr(unsafe.Pointer(&ebss)) { if end < themoduledata.ebss {
end = uintptr(unsafe.Pointer(&ebss)) end = themoduledata.ebss
} }
size := round(end-start, _PageSize) size := round(end-start, _PageSize)
racecall(&__tsan_map_shadow, start, size, 0, 0) racecall(&__tsan_map_shadow, start, size, 0, 0)
......
...@@ -424,15 +424,13 @@ func gomcache() *mcache { ...@@ -424,15 +424,13 @@ func gomcache() *mcache {
return getg().m.mcache return getg().m.mcache
} }
var typelink, etypelink [0]byte
//go:linkname reflect_typelinks reflect.typelinks //go:linkname reflect_typelinks reflect.typelinks
//go:nosplit //go:nosplit
func reflect_typelinks() []*_type { func reflect_typelinks() []*_type {
var ret []*_type var ret []*_type
sp := (*slice)(unsafe.Pointer(&ret)) sp := (*slice)(unsafe.Pointer(&ret))
sp.array = (*byte)(unsafe.Pointer(&typelink)) sp.array = (*byte)(unsafe.Pointer(themoduledata.typelink))
sp.len = uint((uintptr(unsafe.Pointer(&etypelink)) - uintptr(unsafe.Pointer(&typelink))) / unsafe.Sizeof(ret[0])) sp.len = uint((themoduledata.etypelink - themoduledata.typelink) / unsafe.Sizeof(ret[0]))
sp.cap = sp.len sp.cap = sp.len
return ret return ret
} }
......
...@@ -29,15 +29,27 @@ const ( ...@@ -29,15 +29,27 @@ const (
_ArgsSizeUnknown = -0x80000000 _ArgsSizeUnknown = -0x80000000
) )
var ( // moduledata records information about the layout of the executable
pclntable []byte // image. It is written by the linker. Any changes here must be
ftab []functab // matched changes to the code in cmd/internal/ld/symtab.go:symtab.
filetab []uint32 type moduledata struct {
pclntable []byte
pclntab, epclntab, findfunctab struct{} // linker symbols 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 { type functab struct {
entry uintptr entry uintptr
...@@ -64,38 +76,38 @@ func symtabinit() { ...@@ -64,38 +76,38 @@ func symtabinit() {
// See golang.org/s/go12symtab for header: 0xfffffffb, // See golang.org/s/go12symtab for header: 0xfffffffb,
// two zero bytes, a byte giving the PC quantum, // two zero bytes, a byte giving the PC quantum,
// and a byte giving the pointer width in bytes. // and a byte giving the pointer width in bytes.
pcln := (*[8]byte)(unsafe.Pointer(&pclntab)) pcln := (*[8]byte)(unsafe.Pointer(themoduledata.pclntab))
pcln32 := (*[2]uint32)(unsafe.Pointer(&pclntab)) pcln32 := (*[2]uint32)(unsafe.Pointer(themoduledata.pclntab))
if pcln32[0] != 0xfffffffb || pcln[4] != 0 || pcln[5] != 0 || pcln[6] != _PCQuantum || pcln[7] != ptrSize { 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])) 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") throw("invalid function symbol table\n")
} }
// pclntable is all bytes of pclntab symbol. // pclntable is all bytes of pclntab symbol.
sp := (*sliceStruct)(unsafe.Pointer(&pclntable)) sp := (*sliceStruct)(unsafe.Pointer(&themoduledata.pclntable))
sp.array = unsafe.Pointer(&pclntab) sp.array = unsafe.Pointer(themoduledata.pclntab)
sp.len = int(uintptr(unsafe.Pointer(&epclntab)) - uintptr(unsafe.Pointer(&pclntab))) sp.len = int(uintptr(unsafe.Pointer(themoduledata.epclntab)) - uintptr(unsafe.Pointer(themoduledata.pclntab)))
sp.cap = sp.len sp.cap = sp.len
// ftab is lookup table for function by program counter. // ftab is lookup table for function by program counter.
nftab := int(*(*uintptr)(add(unsafe.Pointer(pcln), 8))) nftab := int(*(*uintptr)(add(unsafe.Pointer(pcln), 8)))
p := add(unsafe.Pointer(pcln), 8+ptrSize) p := add(unsafe.Pointer(pcln), 8+ptrSize)
sp = (*sliceStruct)(unsafe.Pointer(&ftab)) sp = (*sliceStruct)(unsafe.Pointer(&themoduledata.ftab))
sp.array = p sp.array = p
sp.len = nftab + 1 sp.len = nftab + 1
sp.cap = sp.len sp.cap = sp.len
for i := 0; i < nftab; i++ { for i := 0; i < nftab; i++ {
// NOTE: ftab[nftab].entry is legal; it is the address beyond the final function. // NOTE: ftab[nftab].entry is legal; it is the address beyond the final function.
if ftab[i].entry > ftab[i+1].entry { if themoduledata.ftab[i].entry > themoduledata.ftab[i+1].entry {
f1 := (*_func)(unsafe.Pointer(&pclntable[ftab[i].funcoff])) f1 := (*_func)(unsafe.Pointer(&themoduledata.pclntable[themoduledata.ftab[i].funcoff]))
f2 := (*_func)(unsafe.Pointer(&pclntable[ftab[i+1].funcoff])) f2 := (*_func)(unsafe.Pointer(&themoduledata.pclntable[themoduledata.ftab[i+1].funcoff]))
f2name := "end" f2name := "end"
if i+1 < nftab { if i+1 < nftab {
f2name = funcname(f2) 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++ { 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") throw("invalid runtime symbol table")
} }
...@@ -104,19 +116,19 @@ func symtabinit() { ...@@ -104,19 +116,19 @@ func symtabinit() {
// The ftab ends with a half functab consisting only of // The ftab ends with a half functab consisting only of
// 'entry', followed by a uint32 giving the pcln-relative // 'entry', followed by a uint32 giving the pcln-relative
// offset of the file table. // offset of the file table.
sp = (*sliceStruct)(unsafe.Pointer(&filetab)) sp = (*sliceStruct)(unsafe.Pointer(&themoduledata.filetab))
end := unsafe.Pointer(&ftab[nftab].funcoff) // just beyond ftab end := unsafe.Pointer(&themoduledata.ftab[nftab].funcoff) // just beyond ftab
fileoffset := *(*uint32)(end) fileoffset := *(*uint32)(end)
sp.array = unsafe.Pointer(&pclntable[fileoffset]) sp.array = unsafe.Pointer(&themoduledata.pclntable[fileoffset])
// length is in first element of array. // length is in first element of array.
// set len to 1 so we can get first element. // set len to 1 so we can get first element.
sp.len = 1 sp.len = 1
sp.cap = 1 sp.cap = 1
sp.len = int(filetab[0]) sp.len = int(themoduledata.filetab[0])
sp.cap = sp.len sp.cap = sp.len
minpc = ftab[0].entry themoduledata.minpc = themoduledata.ftab[0].entry
maxpc = ftab[nftab].entry themoduledata.maxpc = themoduledata.ftab[nftab].entry
} }
// FuncForPC returns a *Func describing the function that contains the // FuncForPC returns a *Func describing the function that contains the
...@@ -147,33 +159,33 @@ func (f *Func) FileLine(pc uintptr) (file string, line int) { ...@@ -147,33 +159,33 @@ func (f *Func) FileLine(pc uintptr) (file string, line int) {
} }
func findfunc(pc uintptr) *_func { func findfunc(pc uintptr) *_func {
if pc < minpc || pc >= maxpc { if pc < themoduledata.minpc || pc >= themoduledata.maxpc {
return nil return nil
} }
const nsub = uintptr(len(findfuncbucket{}.subbuckets)) const nsub = uintptr(len(findfuncbucket{}.subbuckets))
x := pc - minpc x := pc - themoduledata.minpc
b := x / pcbucketsize b := x / pcbucketsize
i := x % pcbucketsize / (pcbucketsize / nsub) 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]) idx := ffb.idx + uint32(ffb.subbuckets[i])
if pc < ftab[idx].entry { if pc < themoduledata.ftab[idx].entry {
throw("findfunc: bad findfunctab entry") throw("findfunc: bad findfunctab entry")
} }
// linear search to find func with pc >= entry. // linear search to find func with pc >= entry.
for ftab[idx+1].entry <= pc { for themoduledata.ftab[idx+1].entry <= pc {
idx++ 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 { func pcvalue(f *_func, off int32, targetpc uintptr, strict bool) int32 {
if off == 0 { if off == 0 {
return -1 return -1
} }
p := pclntable[off:] p := themoduledata.pclntable[off:]
pc := f.entry pc := f.entry
val := int32(-1) val := int32(-1)
for { for {
...@@ -195,7 +207,7 @@ func pcvalue(f *_func, off int32, targetpc uintptr, strict bool) int32 { ...@@ -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") 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 pc = f.entry
val = -1 val = -1
for { for {
...@@ -215,7 +227,7 @@ func cfuncname(f *_func) *byte { ...@@ -215,7 +227,7 @@ func cfuncname(f *_func) *byte {
if f == nil || f.nameoff == 0 { if f == nil || f.nameoff == 0 {
return nil return nil
} }
return (*byte)(unsafe.Pointer(&pclntable[f.nameoff])) return (*byte)(unsafe.Pointer(&themoduledata.pclntable[f.nameoff]))
} }
func funcname(f *_func) string { func funcname(f *_func) string {
...@@ -225,11 +237,11 @@ 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) { func funcline1(f *_func, targetpc uintptr, strict bool) (file string, line int32) {
fileno := int(pcvalue(f, f.pcfile, targetpc, strict)) fileno := int(pcvalue(f, f.pcfile, targetpc, strict))
line = pcvalue(f, f.pcln, 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") // print("looking for ", hex(targetpc), " in ", funcname(f), " got file=", fileno, " line=", lineno, "\n")
return "?", 0 return "?", 0
} }
file = gostringnocopy(&pclntable[filetab[fileno]]) file = gostringnocopy(&themoduledata.pclntable[themoduledata.filetab[fileno]])
return return
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment