github.com/kitech/dl@v0.0.0-20201225001532-be4f4faa4070/dl2/dl.go (about) 1 package dl 2 3 // Still use some cgo type/const/variable 4 // But aims avoid original cgo call to speed up call performance 5 6 /* 7 #cgo CFLAGS: -D_GNU_SOURCE 8 #cgo LDFLAGS: -ldl 9 10 #include <stdlib.h> 11 #include <stdio.h> 12 #include <stdint.h> 13 #include <dlfcn.h> 14 15 // 由于pad有问题,所有的函数都打包成一个void*结构体参数,返回值也打包在这个结构体中 16 int goasmcc_dlopen(struct {char *a0; int a1; void* ret;} *ax) { 17 ax->ret = dlopen(ax->a0, ax->a1); 18 return 0; // just error code 19 } 20 int goasmcc_dlclose(struct {void* a0; int ret; } *ax) { 21 ax->ret = dlclose(ax->a0); 22 return 0; 23 } 24 int goasmcc_dlsym(struct {void* a0; char* a1; void* ret; } *ax) { 25 ax->ret = dlsym(ax->a0, ax->a1); 26 return 0; 27 } 28 int goasmcc_dlerror(struct {char* ret;} *ax) { 29 ax->ret = dlerror(); 30 return 0; 31 } 32 int goasmcc_dladdr(struct {void* a0; Dl_info* a1; int ret;} *ax) { 33 ax->ret = dladdr(ax->a0, ax->a1); 34 return 0; 35 } 36 37 int goasmcc_empty() { 38 char buf[100]; 39 buf[0] = 12; 40 //sprintf(buf, "ttt %d", 999); 41 return 0; 42 } 43 */ 44 import "C" 45 46 import ( 47 "fmt" 48 "unsafe" 49 50 "github.com/kitech/dl/asmcgocall" 51 ) 52 53 // 54 type Flags int 55 56 const ( 57 Lazy Flags = C.RTLD_LAZY 58 Now Flags = C.RTLD_NOW 59 Global Flags = C.RTLD_GLOBAL 60 Local Flags = C.RTLD_LOCAL 61 //NoLoad Flags = C.RTLD_NOLOAD 62 //NoDelete Flags = C.RTLD_NODELETE 63 // First Flags = C.RTLD_FIRST 64 ) 65 66 func EmptyAsmcc(unsafe.Pointer) { asmcgocall.Asmcc(C.goasmcc_empty, nil) } 67 func EmptyCgocc() { C.goasmcc_empty() } 68 69 type Handle struct { 70 fname string 71 c unsafe.Pointer 72 } 73 74 func Open(fname string, flags Flags) (Handle, error) { 75 fname2 := []byte(fname + "\x00") 76 c_str := (*C.char)(unsafe.Pointer(&fname2[0])) 77 78 var argv = struct { 79 p0 *C.char 80 p1 C.int 81 ret unsafe.Pointer 82 }{c_str, C.int(flags), nil} 83 84 asmcgocall.Asmcc(C.goasmcc_dlopen, unsafe.Pointer(&argv)) 85 h := argv.ret 86 if h == nil { 87 err := fmt.Errorf("dl: %s", DLError()) 88 return Handle{}, err 89 } 90 h2 := unsafe.Pointer(uintptr(h)) 91 return Handle{fname, h2}, nil 92 } 93 94 func (h Handle) Close() error { 95 if h.c == nil { 96 return nil 97 } 98 var argv = struct { 99 a0 unsafe.Pointer 100 ret C.int 101 }{h.c, 0} 102 103 asmcgocall.Asmcc(C.goasmcc_dlclose, unsafe.Pointer(&argv)) 104 o := argv.ret 105 if o != C.int(0) { 106 err := fmt.Errorf("dl: %s", DLError()) 107 return err 108 } 109 h.c = nil 110 return nil 111 } 112 113 func (h Handle) RawAddr() uintptr { 114 return uintptr(h.c) 115 } 116 117 func (h Handle) Symbol(symbol string) (uintptr, error) { 118 sym2 := []byte(symbol + "\x00") // ensure \0 119 c_sym := (*C.char)(unsafe.Pointer(&sym2[0])) 120 121 var argv = struct { 122 a0 unsafe.Pointer 123 a1 *C.char 124 ret unsafe.Pointer 125 }{h.c, c_sym, nil} 126 127 asmcgocall.Asmcc(C.goasmcc_dlsym, unsafe.Pointer(&argv)) 128 c_addr := argv.ret 129 if c_addr == nil { 130 err := fmt.Errorf("dl: %s", DLError()) 131 return 0, err 132 } 133 return uintptr(c_addr), nil 134 } 135 136 func (h Handle) DLError() string { return DLError() } 137 func DLError() string { 138 var argv = struct{ ret *C.char }{nil} 139 140 asmcgocall.Asmcc(C.goasmcc_dlerror, unsafe.Pointer(&argv)) 141 c_err := argv.ret 142 if c_err == nil { 143 return "" 144 } 145 return C.GoString(c_err) 146 } 147 148 type Dlinfo struct { 149 Fname string 150 Fbase unsafe.Pointer 151 Sname string 152 Saddr unsafe.Pointer 153 } 154 155 func DlAddr(addr unsafe.Pointer) (res Dlinfo) { 156 var dlainfo C.Dl_info 157 158 var argv = struct { 159 addr unsafe.Pointer 160 info unsafe.Pointer 161 ret C.int 162 }{addr, unsafe.Pointer(&dlainfo), C.int(0)} 163 164 asmcgocall.Asmcc(C.goasmcc_dladdr, unsafe.Pointer(&argv)) 165 rv := int(argv.ret) 166 if rv != 0 { 167 res.Fname = C.GoString(dlainfo.dli_fname) 168 res.Sname = C.GoString(dlainfo.dli_sname) 169 res.Fbase = dlainfo.dli_fbase 170 res.Saddr = dlainfo.dli_saddr 171 } 172 return 173 } 174 175 // TODO 176 func (h Handle) Info() { 177 //C.dlinfo(h.c, 0, nil) 178 panic("not impled") 179 } 180 181 // /* Portable libltdl versions of the system dlopen() API. */ 182 // LT_SCOPE lt_dlhandle lt_dlopen (const char *filename); 183 // LT_SCOPE lt_dlhandle lt_dlopenext (const char *filename); 184 // LT_SCOPE lt_dlhandle lt_dlopenadvise (const char *filename, 185 // lt_dladvise advise); 186 // LT_SCOPE void * lt_dlsym (lt_dlhandle handle, const char *name); 187 // LT_SCOPE const char *lt_dlerror (void); 188 // LT_SCOPE int lt_dlclose (lt_dlhandle handle); 189 190 // EOF