@@ -3,26 +3,13 @@ package gocore
3
3
import (
4
4
"debug/dwarf"
5
5
"fmt"
6
+ "strings"
6
7
7
8
"github.com/randall77/corelib/core"
8
9
)
9
10
10
11
// Core takes a loaded core file and extracts Go information from it.
11
12
func Core (proc * core.Process ) (p * Program , err error ) {
12
- // Check symbol table to make sure we know the addresses
13
- // of some critical runtime data structures.
14
- m , err := proc .Symbols ()
15
- if err != nil {
16
- return nil , err
17
- }
18
- for _ , s := range rtSymbols {
19
- if m ["runtime." + s .name ] == 0 {
20
- // We're missing some address that we need.
21
- return nil , fmt .Errorf ("can't find runtime data structure %s. Is the binary unstripped?" , s .name )
22
- }
23
- }
24
- // TODO: is the symbol table redundant with the DWARF info? Could we just use DWARF?
25
-
26
13
// Make sure we have DWARF info.
27
14
if _ , err := proc .DWARF (); err != nil {
28
15
return nil , err
@@ -50,51 +37,34 @@ func Core(proc *core.Process) (p *Program, err error) {
50
37
dwarfMap : map [dwarf.Type ]* Type {},
51
38
}
52
39
53
- // Load the build version.
54
- a := m ["runtime.buildVersion" ]
55
- ptr := proc .ReadPtr (a )
56
- len := proc .ReadInt (a .Add (proc .PtrSize ()))
57
- b := make ([]byte , len )
58
- proc .ReadAt (b , ptr )
59
- p .buildVersion = string (b )
60
-
61
- // Initialize runtime regions.
62
- p .runtime = map [string ]region {}
63
- for _ , s := range rtSymbols {
64
- p .runtime [s .name ] = region {p : p , a : m ["runtime." + s .name ], typ : s .typ }
40
+ // Initialize everything that just depends on DWARF.
41
+ p .readDWARFTypes ()
42
+ p .readRuntimeConstants ()
43
+ p .readGlobals ()
44
+
45
+ // Find runtime globals we care about. Initialize regions for them.
46
+ p .rtGlobals = map [string ]region {}
47
+ for _ , g := range p .globals {
48
+ if strings .HasPrefix (g .Name , "runtime." ) {
49
+ p .rtGlobals [g .Name [8 :]] = region {p : p , a : g .Addr , typ : g .Type }
50
+ }
65
51
}
66
52
67
- p . readDWARFTypes ()
68
- p .findRuntimeInfo ()
53
+ // Read all the data that depends on runtime globals.
54
+ p .buildVersion = p . rtGlobals [ "buildVersion" ]. String ()
69
55
p .readModules ()
56
+ p .readStackVars ()
70
57
p .readSpans ()
71
58
p .readMs ()
72
59
p .readGs ()
73
- p .findRoots ()
74
60
p .readObjects ()
75
61
p .typeHeap ()
76
- return
77
- }
78
62
79
- // rtSymbols is a list of all the runtime globals that we need to access,
80
- // together with their types.
81
- var rtSymbols = [... ]struct {
82
- name , typ string
83
- }{
84
- {"mheap_" , "runtime.mheap" },
85
- {"memstats" , "runtime.mstats" },
86
- {"sched" , "runtime.schedt" },
87
- {"allfin" , "*runtime.finblock" },
88
- {"finq" , "*runtime.finblock" },
89
- {"allgs" , "[]*runtime.g" },
90
- {"allm" , "*runtime.m" },
91
- {"allp" , "[1]*p" }, // TODO: type depends on _MaxGomaxprocs
92
- {"modulesSlice" , "*[]*runtime.moduledata" },
93
- {"buildVersion" , "string" },
63
+ return p , nil
94
64
}
95
65
96
66
func (p * Program ) readSpans () {
97
- mheap := p .runtime ["mheap_" ]
67
+ mheap := p .rtGlobals ["mheap_" ]
98
68
99
69
spanTableStart := mheap .Field ("spans" ).SlicePtr ().Address ()
100
70
spanTableEnd := spanTableStart .Add (mheap .Field ("spans" ).SliceCap () * p .proc .PtrSize ())
@@ -260,14 +230,7 @@ func (p *Program) readSpans() {
260
230
}
261
231
262
232
func (p * Program ) readModules () {
263
- // Make a runtime name -> Type map for existing DWARF types.
264
- p .runtimeNameMap = map [string ][]* Type {}
265
- for dt , t := range p .dwarfMap {
266
- name := runtimeName (dt )
267
- p .runtimeNameMap [name ] = append (p .runtimeNameMap [name ], t )
268
- }
269
-
270
- ms := p .runtime ["modulesSlice" ].Deref ()
233
+ ms := p .rtGlobals ["modulesSlice" ].Cast ("*[]*runtime.moduledata" ).Deref ()
271
234
n := ms .SliceLen ()
272
235
for i := int64 (0 ); i < n ; i ++ {
273
236
md := ms .SliceIndex (i ).Deref ()
@@ -343,13 +306,13 @@ func (t *Type) ptrs1(s []int64, off int64) []int64 {
343
306
// Convert the address of a runtime._type to a *Type.
344
307
// Guaranteed to return a non-nil *Type.
345
308
func (p * Program ) runtimeType2Type (a core.Address ) * Type {
346
- if t , ok := p .runtimeMap [a ]; ok {
309
+ if t := p .runtimeMap [a ]; t != nil {
347
310
return t
348
311
}
349
312
ptrSize := p .proc .PtrSize ()
350
313
351
314
// Read runtime._type.size
352
- r := region {p : p , a : a , typ : "runtime._type" }
315
+ r := region {p : p , a : a , typ : p . findType ( "runtime._type" ) }
353
316
size := int64 (r .Field ("size" ).Uintptr ())
354
317
355
318
// Find module this type is in.
@@ -413,13 +376,12 @@ func (p *Program) runtimeType2Type(a core.Address) *Type {
413
376
} else {
414
377
// There's no corresponding DWARF type. Make our own.
415
378
t = & Type {name : name , Size : size , Kind : KindStruct }
416
- p .types = append (p .types , t )
417
379
n := t .Size / ptrSize
418
380
419
381
// Types to use for ptr/nonptr fields of runtime types which
420
382
// have no corresponding DWARF type.
421
- ptr := p .runtimeNameMap [ "unsafe.Pointer" ][ 0 ]
422
- nonptr := p .runtimeNameMap [ "uintptr" ][ 0 ]
383
+ ptr := p .findType ( "unsafe.Pointer" )
384
+ nonptr := p .findType ( "uintptr" )
423
385
if ptr == nil || nonptr == nil {
424
386
panic ("ptr / nonptr standins missing" )
425
387
}
@@ -457,7 +419,7 @@ func (m *module) readFunc(r region, pcln region) *Func {
457
419
f .frameSize .read (r .p .proc , pcln .SliceIndex (int64 (r .Field ("pcsp" ).Int32 ())).a )
458
420
459
421
// Parse pcdata and funcdata, which are laid out beyond the end of the _func.
460
- a := r .a .Add (int64 (r .p .rtStructs [ "runtime._func" ]. size ))
422
+ a := r .a .Add (int64 (r .p .findType ( "runtime._func" ). Size ))
461
423
n := r .Field ("npcdata" ).Int32 ()
462
424
for i := int32 (0 ); i < n ; i ++ {
463
425
f .pcdata = append (f .pcdata , r .p .proc .ReadInt32 (a ))
@@ -485,7 +447,7 @@ func pcdata(r region, pcln region, n int64) core.Address {
485
447
if n >= int64 (r .Field ("npcdata" ).Int32 ()) {
486
448
return 0
487
449
}
488
- a := r .a .Add (int64 (r .p .rtStructs [ "runtime._func" ]. size + 4 * n ))
450
+ a := r .a .Add (int64 (r .p .findType ( "runtime._func" ). Size + 4 * n ))
489
451
490
452
off := r .p .proc .ReadInt32 (a )
491
453
return pcln .SliceIndex (int64 (off )).a
@@ -501,12 +463,12 @@ func funcdata(r region, n int64) core.Address {
501
463
if x & 1 != 0 && r .p .proc .PtrSize () == 8 {
502
464
x ++
503
465
}
504
- a := r .a .Add (int64 (r .p .rtStructs [ "runtime._func" ]. size + 4 * int64 (x ) + r .p .proc .PtrSize ()* n ))
466
+ a := r .a .Add (int64 (r .p .findType ( "runtime._func" ). Size + 4 * int64 (x ) + r .p .proc .PtrSize ()* n ))
505
467
return r .p .proc .ReadPtr (a )
506
468
}
507
469
508
470
func (p * Program ) readMs () {
509
- mp := p .runtime ["allm" ]
471
+ mp := p .rtGlobals ["allm" ]
510
472
for mp .Address () != 0 {
511
473
m := mp .Deref ()
512
474
gs := m .Field ("gsignal" )
@@ -521,7 +483,7 @@ func (p *Program) readMs() {
521
483
522
484
func (p * Program ) readGs () {
523
485
// TODO: figure out how to "flush" running Gs.
524
- allgs := p .runtime ["allgs" ]
486
+ allgs := p .rtGlobals ["allgs" ]
525
487
n := allgs .SliceLen ()
526
488
for i := int64 (0 ); i < n ; i ++ {
527
489
r := allgs .SliceIndex (i ).Deref ()
@@ -625,7 +587,7 @@ func (p *Program) readFrame(sp, pc core.Address) *Frame {
625
587
// Find live ptrs in locals
626
588
live := map [core.Address ]bool {}
627
589
if x := int (p .rtConstants ["_FUNCDATA_LocalsPointerMaps" ]); x < len (f .funcdata ) {
628
- locals := region {p : p , a : f .funcdata [x ], typ : "runtime.stackmap" }
590
+ locals := region {p : p , a : f .funcdata [x ], typ : p . findType ( "runtime.stackmap" ) }
629
591
n := locals .Field ("n" ).Int32 () // # of bitmaps
630
592
nbit := locals .Field ("nbit" ).Int32 () // # of bits per bitmap
631
593
idx := f .stackMap .find (off )
@@ -645,7 +607,7 @@ func (p *Program) readFrame(sp, pc core.Address) *Frame {
645
607
}
646
608
// Same for args
647
609
if x := int (p .rtConstants ["_FUNCDATA_ArgsPointerMaps" ]); x < len (f .funcdata ) {
648
- args := region {p : p , a : f .funcdata [x ], typ : "runtime.stackmap" }
610
+ args := region {p : p , a : f .funcdata [x ], typ : p . findType ( "runtime.stackmap" ) }
649
611
n := args .Field ("n" ).Int32 () // # of bitmaps
650
612
nbit := args .Field ("nbit" ).Int32 () // # of bits per bitmap
651
613
idx := f .stackMap .find (off )
0 commit comments