One of EvGoCreate's arguments is a stack for the called function. When the called function is empty, and it is the last function in the executable (I think), the stack's only frame has a PC of zero and no information. This is caused by this series of events:
runtime.traceGoCreate calls (*runtime.traceStackTable).put with the called function's PC and sys.PCQuantum added to it.
(*traceStackTable).dump, which is responsible for writing resolved stack frames to the trace, uses runtime.CallersFrames to turn the PCs into frames
(*runtime.Frames).Next calls runtime.findfunc, which calls runtime.findmoduledatap. findmoduledatap contains a loop, searching for the correct module, based on the module's minpc and maxpc: if datap.minpc <= pc && pc < datap.maxpc { return datap } - In our case, however, pc is equal to datap.maxpc.
Looking at an example binary, the last function in it is
000000000046ca60 <main.baz3>:
func baz3() {}
46ca60: c3 ret
46ca61: cc int3
46ca62: cc int3
46ca63: cc int3
46ca64: cc int3
46ca65: cc int3
46ca66: cc int3
46ca67: cc int3
46ca68: cc int3
46ca69: cc int3
46ca6a: cc int3
46ca6b: cc int3
46ca6c: cc int3
46ca6d: cc int3
46ca6e: cc int3
46ca6f: cc int3
On go baz3, the EvGoCreate event contains a stack with the PC 46ca60 + 1 (I'm on amd64, where sys.PCQuantum is 1). The last module that findmoduledatap looks at has a maxpc of 46ca61, which equals our PC. findmoduledatap returns nil because it couldn't find a matching module, and that bubbles all the way up to (*runtime.Frames).Next returning an empty runtime.Frame.
One of EvGoCreate's arguments is a stack for the called function. When the called function is empty, and it is the last function in the executable (I think), the stack's only frame has a PC of zero and no information. This is caused by this series of events:
runtime.traceGoCreatecalls(*runtime.traceStackTable).putwith the called function's PC andsys.PCQuantumadded to it.(*traceStackTable).dump, which is responsible for writing resolved stack frames to the trace, usesruntime.CallersFramesto turn the PCs into frames(*runtime.Frames).Nextcallsruntime.findfunc, which callsruntime.findmoduledatap.findmoduledatapcontains a loop, searching for the correct module, based on the module'sminpcandmaxpc:if datap.minpc <= pc && pc < datap.maxpc { return datap }- In our case, however,pcis equal todatap.maxpc.Looking at an example binary, the last function in it is
On
go baz3, the EvGoCreate event contains a stack with the PC 46ca60 + 1 (I'm on amd64, where sys.PCQuantum is 1). The last module thatfindmoduledataplooks at has amaxpcof 46ca61, which equals our PC.findmoduledatapreturns nil because it couldn't find a matching module, and that bubbles all the way up to(*runtime.Frames).Nextreturning an empty runtime.Frame.