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))
}
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
// 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 {
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)
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
}
}
// 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
}
}
func initBloc() {
- bloc = memRound(uintptr(unsafe.Pointer(&end)))
+ bloc = memRound(themoduledata.end)
}
func sbrk(n uintptr) unsafe.Pointer {
// 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")
_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
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
}
// 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 {
"unsafe"
)
-var text struct{}
-
func dumpregs(r *context) {
print("eax ", hex(r.eax), "\n")
print("ebx ", hex(r.ebx), "\n")
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
}
"unsafe"
)
-var text struct{}
-
func dumpregs(r *context) {
print("rax ", hex(r.rax), "\n")
print("rbx ", hex(r.rbx), "\n")
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
}
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 {
// 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
// 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)
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
}
_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
// 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")
}
// 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
}
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 {
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 {
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 {
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
}