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  }