github.com/dearplain/goloader@v0.0.0-20190107071432-2b1e47d74273/examples/loader/loader.go (about) 1 package main 2 3 import ( 4 "cmd/objfile/goobj" 5 "flag" 6 "fmt" 7 "net/http" 8 "os" 9 "runtime" 10 "strings" 11 "sync" 12 "time" 13 "unsafe" 14 15 "github.com/dearplain/goloader" 16 "github.com/kr/pretty" 17 ) 18 19 func mustOK(err error) { 20 if err != nil { 21 panic(err) 22 } 23 } 24 25 type arrayFlags struct { 26 File []string 27 PkgPath []string 28 } 29 30 func (i *arrayFlags) String() string { 31 return "my string representation" 32 } 33 34 func (i *arrayFlags) Set(value string) error { 35 s := strings.Split(value, ":") 36 i.File = append(i.File, s[0]) 37 var path string 38 if len(s) > 1 { 39 path = s[1] 40 } 41 i.PkgPath = append(i.PkgPath, path) 42 return nil 43 } 44 45 func main() { 46 47 var files arrayFlags 48 flag.Var(&files, "o", "load go object file") 49 var pkgpath = flag.String("p", "", "package path") 50 var parseFile = flag.String("parse", "", "parse go object file") 51 var run = flag.String("run", "main.main", "run function") 52 var times = flag.Int("times", 1, "run count") 53 54 flag.Parse() 55 56 if *parseFile != "" { 57 parse(parseFile, pkgpath) 58 return 59 } 60 61 if len(files.File) == 0 { 62 flag.PrintDefaults() 63 return 64 } 65 66 symPtr := make(map[string]uintptr) 67 goloader.RegSymbol(symPtr) 68 69 goloader.RegTypes(symPtr, time.Duration(0), time.Unix(0, 0)) 70 goloader.RegTypes(symPtr, runtime.LockOSThread) 71 // most of time you don't need to register function, but if loader complain about it, you have to. 72 goloader.RegTypes(symPtr, http.ListenAndServe, http.Dir("/"), 73 http.Handler(http.FileServer(http.Dir("/"))), http.FileServer, http.HandleFunc, 74 &http.Request{}) 75 w := sync.WaitGroup{} 76 rw := sync.RWMutex{} 77 goloader.RegTypes(symPtr, &w, w.Wait, &rw) 78 79 reloc, err := goloader.ReadObjs(files.File, files.PkgPath) 80 if err != nil { 81 fmt.Println(err) 82 } 83 84 var mmapByte []byte 85 for i := 0; i < *times; i++ { 86 codeModule, err := goloader.Load(reloc, symPtr) 87 if err != nil { 88 fmt.Println("Load error:", err) 89 } 90 runFuncPtr := codeModule.Syms[*run] 91 funcPtrContainer := (uintptr)(unsafe.Pointer(&runFuncPtr)) 92 runFunc := *(*func())(unsafe.Pointer(&funcPtrContainer)) 93 runFunc() 94 codeModule.Unload() 95 96 // a strict test, try to make mmap random 97 if mmapByte == nil { 98 mmapByte, err = goloader.Mmap(1024) 99 if err != nil { 100 fmt.Println(err) 101 } 102 b := make([]byte, 1024) 103 copy(mmapByte, b) // reset all bytes 104 } else { 105 goloader.Munmap(mmapByte) 106 mmapByte = nil 107 } 108 } 109 110 } 111 112 func parse(file, pkgpath *string) { 113 114 if *file == "" { 115 flag.PrintDefaults() 116 return 117 } 118 119 f, err := os.Open(*file) 120 if err != nil { 121 fmt.Printf("%# v\n", err) 122 return 123 } 124 obj, err := goobj.Parse(f, *pkgpath) 125 pretty.Printf("%# v\n", obj) 126 f.Close() 127 if err != nil { 128 fmt.Printf("error reading %s: %v\n", *file, err) 129 return 130 } 131 }