github.com/zeebo/goof@v0.0.0-20230907150950-e9457bc94477/troop_globals.go (about)

     1  package goof
     2  
     3  import (
     4  	"debug/dwarf"
     5  	"reflect"
     6  	"regexp"
     7  	"sort"
     8  	"strings"
     9  	"unsafe"
    10  
    11  	"github.com/zeebo/errs"
    12  )
    13  
    14  var statictmpRe = regexp.MustCompile(`statictmp_\d+$`)
    15  
    16  func (t *Troop) addGlobals() error {
    17  	reader := t.data.Reader()
    18  
    19  	for {
    20  		entry, err := reader.Next()
    21  		if err != nil {
    22  			return errs.Wrap(err)
    23  		}
    24  		if entry == nil {
    25  			break
    26  		}
    27  
    28  		if entry.Tag != dwarf.TagVariable {
    29  			continue
    30  		}
    31  
    32  		name, ok := entry.Val(dwarf.AttrName).(string)
    33  		if !ok {
    34  			continue
    35  		}
    36  
    37  		// filter out some values that aren't useful and just clutter stuff
    38  		if strings.Contains(name, "ยท") {
    39  			continue
    40  		}
    41  		if statictmpRe.MatchString(name) {
    42  			continue
    43  		}
    44  
    45  		loc, err := entryLocation(t.data, entry)
    46  		if err != nil {
    47  			continue
    48  		}
    49  
    50  		dtyp, err := entryType(t.data, entry)
    51  		if err != nil {
    52  			continue
    53  		}
    54  
    55  		dname := dwarfTypeName(dtyp)
    56  		if dname == "<unspecified>" || dname == "" {
    57  			continue
    58  		}
    59  
    60  		rtyp := t.types[dname]
    61  		if rtyp == nil {
    62  			continue
    63  		}
    64  
    65  		ptr := unsafe.Pointer(uintptr(loc))
    66  		t.globals[name] = reflect.NewAt(rtyp, ptr).Elem()
    67  	}
    68  
    69  	return nil
    70  }
    71  
    72  func (t *Troop) Globals() ([]string, error) {
    73  	if err := t.check(); err != nil {
    74  		return nil, err
    75  	}
    76  	out := make([]string, 0, len(t.globals))
    77  	for name := range t.globals {
    78  		out = append(out, name)
    79  	}
    80  	sort.Strings(out)
    81  	return out, nil
    82  }
    83  
    84  func (t *Troop) Global(name string) (reflect.Value, error) {
    85  	if err := t.check(); err != nil {
    86  		return reflect.Value{}, t.err
    87  	}
    88  	return t.globals[name], nil
    89  }