Source File
symtab.go
Belonging Package
runtime
package runtime
import (
)
frames []Frame
frameStore [2]Frame
}
--
}
:= funcname()
if := funcdata(, _FUNCDATA_InlTree); != nil {
:= pcdatavalue1(, _PCDATA_InlTreeIndex, , nil, false)
= nil
})
}
switch len(.frames) {
case 0: // In the rare case when there are no frames at all, we return Frame{}.
return
case 1:
= .frames[0]
.frames = .frameStore[:0]
case 2:
= .frames[0]
.frameStore[0] = .frames[1]
.frames = .frameStore[:1]
default:
= .frames[0]
.frames = .frames[1:]
}
= len(.frames) > 0
return
}
:= funcdata(, _FUNCDATA_InlTree)
return
}
= [:len()-1]
var pcvalueCache
:= (*[1 << 20]inlinedCall)()
for {
:= pcdatavalue(, _PCDATA_InlTreeIndex, , &)
if < 0 {
break
}
} else {
= append(, )
}
= append(, )
return
}
func ( uintptr) []Frame {
:= cgoSymbolizerArg{pc: }
callCgoSymbolizer(&)
})
if .more == 0 {
break
}
callCgoSymbolizer(&)
}
.pc = 0
callCgoSymbolizer(&)
return
}
const (
_PCDATA_UnsafePoint = 0
_PCDATA_StackMapIndex = 1
_PCDATA_InlTreeIndex = 2
_FUNCDATA_ArgsPointerMaps = 0
_FUNCDATA_LocalsPointerMaps = 1
_FUNCDATA_StackObjects = 2
_FUNCDATA_InlTree = 3
_FUNCDATA_OpenCodedDeferInfo = 4
_ArgsSizeUnknown = -0x80000000
)
_PCDATA_UnsafePointSafe = -1 // Safe for async preemption
_PCDATA_UnsafePointUnsafe = -2 // Unsafe for async preemption
_PCDATA_Restart1 = -3
_PCDATA_Restart2 = -4
_PCDATA_RestartAtEntry = -5
)
type funcID uint8
const (
funcID_normal funcID = iota // not a special function
funcID_runtime_main
funcID_goexit
funcID_jmpdefer
funcID_mcall
funcID_morestack
funcID_mstart
funcID_rt0_go
funcID_asmcgocall
funcID_sigpanic
funcID_runfinq
funcID_gcBgMarkWorker
funcID_systemstack_switch
funcID_systemstack
funcID_cgocallback
funcID_gogo
funcID_externalthreadhandler
funcID_debugCallV1
funcID_gopanic
funcID_panicwrap
funcID_handleAsyncEvent
funcID_asyncPreempt
funcID_wrapper // any autogenerated code (hash/eq algorithms, method wrappers, etc.)
)
type pcHeader struct {
magic uint32 // 0xFFFFFFFA
pad1, pad2 uint8 // 0,0
minLC uint8 // min instruction size
ptrSize uint8 // size of a ptr in bytes
nfunc int // number of functions in the module
nfiles uint // number of entries in the file tab.
funcnameOffset uintptr // offset to the funcnametab variable from pcHeader
cuOffset uintptr // offset to the cutab variable from pcHeader
filetabOffset uintptr // offset to the filetab variable from pcHeader
pctabOffset uintptr // offset to the pctab varible from pcHeader
pclnOffset uintptr // offset to the pclntab variable from pcHeader
}
type moduledata struct {
pcHeader *pcHeader
funcnametab []byte
cutab []uint32
filetab []byte
pctab []byte
pclntable []byte
ftab []functab
findfunctab uintptr
minpc, maxpc uintptr
text, etext uintptr
noptrdata, enoptrdata uintptr
data, edata uintptr
bss, ebss uintptr
noptrbss, enoptrbss uintptr
end, gcdata, gcbss uintptr
types, etypes uintptr
textsectmap []textsect
typelinks []int32 // offsets from types
itablinks []*itab
ptab []ptabEntry
pluginpath string
pkghashes []modulehash
modulename string
modulehashes []modulehash
hasmain uint8 // 1 if module contains the main function, 0 otherwise
gcdatamask, gcbssmask bitvector
typemap map[typeOff]*_type // offset to *_rtype in previous module
bad bool // module failed to load and should be ignored
next *moduledata
}
type modulehash struct {
modulename string
linktimehash string
runtimehash *string
}
var pinnedTypemaps []map[typeOff]*_type
var firstmoduledata moduledata // linker symbol
var lastmoduledatap *moduledata // linker symbol
var modulesSlice *[]*moduledata // see activeModules
func () []*moduledata {
:= (*[]*moduledata)(atomic.Loadp(unsafe.Pointer(&modulesSlice)))
if == nil {
return nil
}
return *
}
func () {
:= new([]*moduledata)
for := &firstmoduledata; != nil; = .next {
if .bad {
continue
}
* = append(*, )
if .gcdatamask == (bitvector{}) {
.gcdatamask = progToPointerMask((*byte)(unsafe.Pointer(.gcdata)), .edata-.data)
.gcbssmask = progToPointerMask((*byte)(unsafe.Pointer(.gcbss)), .ebss-.bss)
}
}
for , := range * {
if .hasmain != 0 {
(*)[0] =
(*)[] = &firstmoduledata
break
}
}
atomicstorep(unsafe.Pointer(&modulesSlice), unsafe.Pointer())
}
type functab struct {
entry uintptr
funcoff uintptr
}
type findfuncbucket struct {
idx uint32
subbuckets [16]byte
}
func () {
for := &firstmoduledata; != nil; = .next {
moduledataverify1()
}
}
const debugPcln = false
if .ftab[].entry > .ftab[+1].entry {
:= funcInfo{(*_func)(unsafe.Pointer(&.pclntable[.ftab[].funcoff])), }
:= funcInfo{(*_func)(unsafe.Pointer(&.pclntable[.ftab[+1].funcoff])), }
:= "end"
if +1 < {
= funcname()
}
println("function symbol table not sorted by program counter:", hex(.ftab[].entry), funcname(), ">", hex(.ftab[+1].entry), )
for := 0; <= ; ++ {
print("\t", hex(.ftab[].entry), " ", funcname(funcInfo{(*_func)(unsafe.Pointer(&.pclntable[.ftab[].funcoff])), }), "\n")
}
if GOOS == "aix" && isarchive {
println("-Wl,-bnoobjreorder is mandatory on aix/ppc64 with c-archive")
}
throw("invalid runtime symbol table")
}
}
if .minpc != .ftab[0].entry ||
.maxpc != .ftab[].entry {
throw("minpc or maxpc invalid")
}
for , := range .modulehashes {
if .linktimehash != *.runtimehash {
println("abi mismatch detected between", .modulename, "and", .modulename)
throw("abi mismatch")
}
}
}
if := pcdatavalue1(, _PCDATA_InlTreeIndex, , nil, false); >= 0 {
:= (*[1 << 20]inlinedCall)()
:= funcnameFromNameoff(, [].func_)
, := funcline(, )
:= &funcinl{
entry: .entry, // entry of the real (the outermost) function.
name: ,
file: ,
line: int(),
}
return (*Func)(unsafe.Pointer())
}
}
return ._Func()
}
, := funcline1(.funcInfo(), , false)
return , int()
}
func ( uintptr) *moduledata {
for := &firstmoduledata; != nil; = .next {
if .minpc <= && < .maxpc {
return
}
}
return nil
}
type funcInfo struct {
*_func
datap *moduledata
}
func ( funcInfo) () bool {
return ._func != nil
}
func ( funcInfo) () *Func {
return (*Func)(unsafe.Pointer(._func))
}
func ( uintptr) funcInfo {
:= findmoduledatap()
if == nil {
return funcInfo{}
}
const = uintptr(len(findfuncbucket{}.subbuckets))
:= - .minpc
:= / pcbucketsize
:= % pcbucketsize / (pcbucketsize / )
:= (*findfuncbucket)(add(unsafe.Pointer(.findfunctab), *unsafe.Sizeof(findfuncbucket{})))
:= .idx + uint32(.subbuckets[])
return funcInfo{}
}
return funcInfo{(*_func)(unsafe.Pointer(&.pclntable[])), }
}
type pcvalueCache struct {
entries [2][8]pcvalueCacheEnt
}
if != nil {
:= pcvalueCacheKey()
:= &.entries[][]
if .off == && .targetpc == {
return .val, 0
}
}
}
if !.valid() {
if && panicking == 0 {
print("runtime: no module data for ", hex(.entry), "\n")
throw("no module data")
}
return -1, 0
}
:= .datap
:= .pctab[:]
:= .entry
:=
:= int32(-1)
for {
var bool
, = step(, &, &, == .entry)
if ! {
break
}
if panicking != 0 || ! {
return -1, 0
}
print("runtime: invalid pc-encoded table f=", funcname(), " pc=", hex(), " targetpc=", hex(), " tab=", , "\n")
= .pctab[:]
= .entry
= -1
for {
var bool
, = step(, &, &, == .entry)
if ! {
break
}
print("\tvalue=", , " until pc=", hex(), "\n")
}
throw("invalid runtime symbol table")
return -1, 0
}
func ( funcInfo) *byte {
if !.valid() || .nameoff == 0 {
return nil
}
return &.datap.funcnametab[.nameoff]
}
func ( funcInfo) string {
return gostringnocopy(cfuncname())
}
func ( funcInfo) string {
:= funcname()
:= len() - 1
for ; > 0; -- {
if [] == '/' {
break
}
}
for ; < len(); ++ {
if [] == '.' {
break
}
}
return [:]
}
func ( funcInfo, int32) *byte {
if !.valid() {
return nil
}
return &.datap.funcnametab[]
}
func ( funcInfo, int32) string {
return gostringnocopy(cfuncnameFromNameoff(, ))
}
func ( funcInfo, int32) string {
:= .datap
if !.valid() {
return "?"
return "?", 0
}
= funcfile(, )
return
}
func ( funcInfo, uintptr) ( string, int32) {
return funcline1(, , true)
}
func ( funcInfo, uintptr, *pcvalueCache) int32 {
, := pcvalue(, .pcsp, , , true)
if &(sys.PtrSize-1) != 0 {
print("invalid spdelta ", funcname(), " ", hex(.entry), " ", hex(), " ", hex(.pcsp), " ", , "\n")
}
return
}
func ( funcInfo) int32 {
:= .datap
:= .pctab[.pcsp:]
:= .entry
:= int32(-1)
:= int32(0)
for {
var bool
, = step(, &, &, == .entry)
if ! {
return
}
if > {
=
}
}
}
func ( funcInfo, uint32) uint32 {
return *(*uint32)(add(unsafe.Pointer(&.nfuncdata), unsafe.Sizeof(.nfuncdata)+uintptr()*4))
}
func ( funcInfo, uint32, uintptr, *pcvalueCache) int32 {
if >= .npcdata {
return -1
}
, := pcvalue(, pcdatastart(, ), , , true)
return
}
func ( funcInfo, uint32, uintptr, *pcvalueCache, bool) int32 {
if >= .npcdata {
return -1
}
, := pcvalue(, pcdatastart(, ), , , )
return
}
func ( funcInfo, uint32, uintptr) (int32, uintptr) {
if >= .npcdata {
return -1, 0
}
return pcvalue(, pcdatastart(, ), , nil, true)
}
func ( funcInfo, uint8) unsafe.Pointer {
if < 0 || >= .nfuncdata {
return nil
}
:= add(unsafe.Pointer(&.nfuncdata), unsafe.Sizeof(.nfuncdata)+uintptr(.npcdata)*4)
if sys.PtrSize == 8 && uintptr()&4 != 0 {
if uintptr(unsafe.Pointer(._func))&4 != 0 {
println("runtime: misaligned func", ._func)
}
= add(, 4)
}
return *(*unsafe.Pointer)(add(, uintptr()*sys.PtrSize))
}
type inlinedCall struct {
parent int16 // index of parent in the inltree, or < 0
funcID funcID // type of the called function
_ byte
file int32 // perCU file index for inlined call. See cmd/link:pcln.go
line int32 // line number of the call site
func_ int32 // offset into pclntab for name of called function
parentPc int32 // position of an instruction whose source position is the call site (offset from entry)
![]() |
The pages are generated with Golds v0.3.2-preview. (GOOS=darwin GOARCH=amd64) Golds is a Go 101 project developed by Tapir Liu. PR and bug reports are welcome and can be submitted to the issue list. Please follow @Go100and1 (reachable from the left QR code) to get the latest news of Golds. |