github.com/zeebo/goof@v0.0.0-20230907150950-e9457bc94477/dwarf_helpers.go (about) 1 package goof 2 3 import ( 4 "debug/dwarf" 5 "encoding/binary" 6 "unsafe" 7 8 "github.com/zeebo/errs" 9 ) 10 11 func dwarfTypeName(dtyp dwarf.Type) string { 12 // for some reason the debug/dwarf package doesn't set the Name field 13 // on the common type for struct fields. what is this misery? 14 switch dtyp := dtyp.(type) { 15 case *dwarf.StructType: 16 return dtyp.StructName 17 default: 18 return dtyp.Common().Name 19 } 20 } 21 22 func getFunctionArgTypes(data *dwarf.Data, entry *dwarf.Entry) ( 23 []dwarf.Type, error) { 24 25 reader := data.Reader() 26 27 reader.Seek(entry.Offset) 28 _, err := reader.Next() 29 if err != nil { 30 return nil, err 31 } 32 33 var args []dwarf.Type 34 for { 35 child, err := reader.Next() 36 if err != nil { 37 return nil, err 38 } 39 if child == nil || child.Tag == 0 { 40 break 41 } 42 43 if child.Tag != dwarf.TagFormalParameter { 44 continue 45 } 46 47 dtyp, err := entryType(data, child) 48 if err != nil { 49 return nil, err 50 } 51 52 args = append(args, dtyp) 53 } 54 55 return args, nil 56 } 57 58 func entryType(data *dwarf.Data, entry *dwarf.Entry) (dwarf.Type, error) { 59 off, ok := entry.Val(dwarf.AttrType).(dwarf.Offset) 60 if !ok { 61 return nil, errs.New("unable to find type offset for entry") 62 } 63 return data.Type(off) 64 } 65 66 func entryLocation(data *dwarf.Data, entry *dwarf.Entry) (uint64, error) { 67 loc, ok := entry.Val(dwarf.AttrLocation).([]byte) 68 if !ok { 69 return 0, errs.New("unable to find location for entry") 70 } 71 if len(loc) == 0 { 72 return 0, errs.New("location had no data") 73 } 74 75 // only support this opcode. did you know dwarf location information is 76 // a stack based programming language with opcodes and stuff? i wonder 77 // how many interpreters for that have code execution bugs in them. 78 if loc[0] != 0x03 { 79 return 0, errs.New("can't interpret location information") 80 } 81 82 // oh man let's also just assume that the dwarf info is written in the 83 // same order as the host! WHAT COULD GO WRONG?! 84 switch len(loc) - 1 { 85 case 4: 86 return uint64(hostOrder.Uint32(loc[1:])), nil 87 case 8: 88 return uint64(hostOrder.Uint64(loc[1:])), nil 89 default: 90 return 0, errs.New("what kind of computer is this?") 91 } 92 } 93 94 var hostOrder binary.ByteOrder 95 96 func init() { 97 i := 1 98 data := (*[4]byte)(unsafe.Pointer(&i)) 99 100 if data[0] == 0 { 101 hostOrder = binary.BigEndian 102 } else { 103 hostOrder = binary.LittleEndian 104 } 105 }