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

     1  package main
     2  
     3  import (
     4  	"debug/dwarf"
     5  	"fmt"
     6  	"log"
     7  	"os"
     8  	"reflect"
     9  	"runtime"
    10  	"unsafe"
    11  
    12  	"github.com/go-delve/delve/pkg/dwarf/godwarf"
    13  	"github.com/go-delve/delve/pkg/proc"
    14  )
    15  
    16  func main() {
    17  	path, err := os.Executable()
    18  	if err != nil {
    19  		log.Fatalln(err)
    20  	}
    21  
    22  	bi := proc.NewBinaryInfo(runtime.GOOS, runtime.GOARCH)
    23  	err = bi.LoadBinaryInfo(path, 0, nil)
    24  	if err != nil {
    25  		log.Fatalln(err)
    26  	}
    27  	mds, err := loadModuleData(bi, new(localMemory))
    28  	if err != nil {
    29  		log.Fatalln(err)
    30  	}
    31  
    32  	types, err := bi.Types()
    33  	if err != nil {
    34  		log.Fatalln(err)
    35  	}
    36  
    37  	for _, name := range types {
    38  		dwarfType, err := findType(bi, name)
    39  		if err != nil {
    40  			continue
    41  		}
    42  
    43  		typeAddr, err := dwarfToRuntimeType(bi, mds, dwarfType, name)
    44  		if err != nil {
    45  			continue
    46  		}
    47  
    48  		typ := reflect.TypeOf(*(*interface{})(unsafe.Pointer(&typeAddr)))
    49  		log.Printf("load type name:%s type:%s\n", name, typ)
    50  	}
    51  }
    52  
    53  // delve counterpart to runtime.moduledata
    54  type moduleData struct {
    55  	text, etext   uint64
    56  	types, etypes uint64
    57  	typemapVar    *proc.Variable
    58  }
    59  
    60  //go:linkname findType github.com/go-delve/delve/pkg/proc.(*BinaryInfo).findType
    61  func findType(bi *proc.BinaryInfo, name string) (godwarf.Type, error)
    62  
    63  //go:linkname loadModuleData github.com/go-delve/delve/pkg/proc.loadModuleData
    64  func loadModuleData(bi *proc.BinaryInfo, mem proc.MemoryReadWriter) ([]moduleData, error)
    65  
    66  //go:linkname imageToModuleData github.com/go-delve/delve/pkg/proc.(*BinaryInfo).imageToModuleData
    67  func imageToModuleData(bi *proc.BinaryInfo, image *proc.Image, mds []moduleData) *moduleData
    68  
    69  type localMemory int
    70  
    71  func (mem *localMemory) ReadMemory(data []byte, addr uint64) (int, error) {
    72  	buf := *(*[]byte)(unsafe.Pointer(&reflect.SliceHeader{Data: uintptr(addr), Len: len(data), Cap: len(data)}))
    73  	copy(data, buf)
    74  	return len(data), nil
    75  }
    76  
    77  func (mem *localMemory) WriteMemory(addr uint64, data []byte) (int, error) {
    78  	return 0, fmt.Errorf("not support")
    79  }
    80  
    81  func dwarfToRuntimeType(bi *proc.BinaryInfo, mds []moduleData, typ godwarf.Type, name string) (typeAddr uint64, err error) {
    82  	if typ.Common().Index >= len(bi.Images) {
    83  		return 0, fmt.Errorf("could not find image for type %s", name)
    84  	}
    85  	img := bi.Images[typ.Common().Index]
    86  	rdr := img.DwarfReader()
    87  	rdr.Seek(typ.Common().Offset)
    88  	e, err := rdr.Next()
    89  	if err != nil {
    90  		return 0, fmt.Errorf("could not find dwarf entry for type:%s err:%s", name, err)
    91  	}
    92  	entryName, ok := e.Val(dwarf.AttrName).(string)
    93  	if !ok || entryName != name {
    94  		return 0, fmt.Errorf("could not find name for type:%s entry:%s", name, entryName)
    95  	}
    96  	off, ok := e.Val(godwarf.AttrGoRuntimeType).(uint64)
    97  	if !ok || off == 0 {
    98  		return 0, fmt.Errorf("could not find runtime type for type:%s", name)
    99  	}
   100  
   101  	md := imageToModuleData(bi, img, mds)
   102  	if md == nil {
   103  		return 0, fmt.Errorf("could not find module data for type %s", name)
   104  	}
   105  
   106  	typeAddr = md.types + off
   107  	if typeAddr < md.types || typeAddr >= md.etypes {
   108  		return off, nil
   109  	}
   110  	return typeAddr, nil
   111  }