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