github.com/lsg2020/gort@v0.0.0-20220515072951-7a7794baa036/gort_globals.go (about)

     1  package gort
     2  
     3  import (
     4  	"debug/dwarf"
     5  	"reflect"
     6  	"unsafe"
     7  
     8  	"github.com/go-delve/delve/pkg/proc"
     9  )
    10  
    11  func (d *DwarfRT) ForeachGlobal(f func(name string, v reflect.Value)) error {
    12  	if err := d.check(); err != nil {
    13  		return err
    14  	}
    15  	if d.globals == nil {
    16  		d.loadGlobals()
    17  	}
    18  
    19  	for name, v := range d.globals {
    20  		f(name, v)
    21  	}
    22  	return nil
    23  }
    24  
    25  func (d *DwarfRT) FindGlobal(name string) (reflect.Value, error) {
    26  	if err := d.check(); err != nil {
    27  		return reflect.Value{}, err
    28  	}
    29  	if d.globals == nil {
    30  		d.loadGlobals()
    31  	}
    32  
    33  	v, ok := d.globals[name]
    34  	if !ok {
    35  		return reflect.Value{}, ErrNotFound
    36  	}
    37  	return v, nil
    38  }
    39  
    40  func (d *DwarfRT) loadGlobals() {
    41  	d.globals = make(map[string]reflect.Value)
    42  
    43  	packageVars := reflect.ValueOf(d.bi).Elem().FieldByName("packageVars")
    44  	if packageVars.IsValid() {
    45  		for i := 0; i < packageVars.Len(); i++ {
    46  			rv := packageVars.Index(i)
    47  			rName := rv.FieldByName("name")
    48  			rAddr := rv.FieldByName("addr")
    49  			rOffset := rv.FieldByName("offset")
    50  			rCU := rv.FieldByName("cu")
    51  			if !rName.IsValid() || !rAddr.IsValid() || !rCU.IsValid() || !rOffset.IsValid() {
    52  				continue
    53  			}
    54  			rImage := rCU.Elem().FieldByName("image")
    55  			if !rImage.IsValid() {
    56  				continue
    57  			}
    58  			rDwarf := rImage.Elem().FieldByName("dwarf")
    59  			if !rDwarf.IsValid() {
    60  				continue
    61  			}
    62  			image := (*proc.Image)(unsafe.Pointer(rImage.Pointer()))
    63  			dwarfData := (*dwarf.Data)(unsafe.Pointer(rDwarf.Pointer()))
    64  
    65  			reader := image.DwarfReader()
    66  			reader.Seek(dwarf.Offset(rOffset.Uint()))
    67  			entry, err := reader.Next()
    68  			if err != nil || entry == nil || entry.Tag != dwarf.TagVariable {
    69  				continue
    70  			}
    71  			name, ok := entry.Val(dwarf.AttrName).(string)
    72  			if !ok || rName.String() != name {
    73  				continue
    74  			}
    75  
    76  			dtyp, err := entryType(dwarfData, entry)
    77  			if err != nil {
    78  				continue
    79  			}
    80  			dname := dwarfTypeName(dtyp)
    81  			if dname == "<unspecified>" || dname == "" {
    82  				continue
    83  			}
    84  
    85  			rtyp, err := d.FindType(dname)
    86  			if err != nil || rtyp == nil {
    87  				continue
    88  			}
    89  			d.globals[name] = reflect.NewAt(rtyp, unsafe.Pointer(uintptr(rAddr.Uint()))).Elem()
    90  		}
    91  	}
    92  }