detached 0f3e4f8

purego: implement dlerror & dlclose (#14)

commit
0f3e4f83313426b50eecae8b43d626551631be62
author
TotallyGamerJet · · 2022-08-09 00:23 UTC
committer
GitHub · · 2022-08-09 00:23 UTC
parent
78cdc29
signature
GPG Unverified4AEE18F83AFDEB23 The key is unknown
3 files · +46 -2
M dlfcn.go +31 -2
@@ -7,6 +7,7 @@
77 package purego
88
99 import (
10+ "reflect"
1011 "runtime"
1112 "unsafe"
1213
@@ -17,8 +18,8 @@ const RTLD_GLOBAL = 0x8
1718
1819 const RTLD_DEFAULT = ^uintptr(1)
1920
20-func Dlopen(name string, mode int) uintptr {
21- bs := strings.CString(name)
21+func Dlopen(path string, mode int) uintptr {
22+ bs := strings.CString(path)
2223 ret, _, _ := SyscallN(dlopenABI0, uintptr(unsafe.Pointer(bs)), uintptr(mode), 0)
2324 runtime.KeepAlive(bs)
2425 return ret
@@ -31,6 +32,34 @@ func Dlsym(handle uintptr, name string) uintptr {
3132 return ret
3233 }
3334
35+func Dlerror() string {
36+ // msg is only valid until the next call to Dlerror
37+ // which is why it gets copied into a Go string
38+ msg, _, _ := SyscallN(dlerrorABI0)
39+ if msg == 0 {
40+ return ""
41+ }
42+ var length int
43+ for {
44+ // use unsafe.Add once we reach 1.17
45+ if *(*byte)(unsafe.Pointer(msg + uintptr(length))) == '\x00' {
46+ break
47+ }
48+ length++
49+ }
50+ // use unsafe.Slice once we reach 1.17
51+ s := make([]byte, length)
52+ copy(s, *(*[]byte)(unsafe.Pointer(&reflect.SliceHeader{Data: msg, Len: length, Cap: length})))
53+ return string(s)
54+}
55+
56+func Dlclose(handle uintptr) bool {
57+ ret, _, _ := SyscallN(dlcloseABI0, handle)
58+ return ret != 0
59+}
60+
3461 // these functions exist in dlfcn_stubs.s and are calling C functions linked to in dlfcn_GOOS.go
3562 var dlopenABI0 uintptr
3663 var dlsymABI0 uintptr
64+var dlcloseABI0 uintptr
65+var dlerrorABI0 uintptr
@@ -7,6 +7,7 @@
7 package purego7 package purego
8 8
9 import (9 import (
10+ "reflect"
10 "runtime"11 "runtime"
11 "unsafe"12 "unsafe"
12 13
@@ -17,8 +18,8 @@ const RTLD_GLOBAL = 0x8
17 18
18 const RTLD_DEFAULT = ^uintptr(1)19 const RTLD_DEFAULT = ^uintptr(1)
19 20
20-func Dlopen(name string, mode int) uintptr {21+func Dlopen(path string, mode int) uintptr {
21- bs := strings.CString(name)22+ bs := strings.CString(path)
22 ret, _, _ := SyscallN(dlopenABI0, uintptr(unsafe.Pointer(bs)), uintptr(mode), 0)23 ret, _, _ := SyscallN(dlopenABI0, uintptr(unsafe.Pointer(bs)), uintptr(mode), 0)
23 runtime.KeepAlive(bs)24 runtime.KeepAlive(bs)
24 return ret25 return ret
@@ -31,6 +32,34 @@ func Dlsym(handle uintptr, name string) uintptr {
31 return ret32 return ret
32 }33 }
33 34
35+func Dlerror() string {
36+ // msg is only valid until the next call to Dlerror
37+ // which is why it gets copied into a Go string
38+ msg, _, _ := SyscallN(dlerrorABI0)
39+ if msg == 0 {
40+ return ""
41+ }
42+ var length int
43+ for {
44+ // use unsafe.Add once we reach 1.17
45+ if *(*byte)(unsafe.Pointer(msg + uintptr(length))) == '\x00' {
46+ break
47+ }
48+ length++
49+ }
50+ // use unsafe.Slice once we reach 1.17
51+ s := make([]byte, length)
52+ copy(s, *(*[]byte)(unsafe.Pointer(&reflect.SliceHeader{Data: msg, Len: length, Cap: length})))
53+ return string(s)
54+}
55+
56+func Dlclose(handle uintptr) bool {
57+ ret, _, _ := SyscallN(dlcloseABI0, handle)
58+ return ret != 0
59+}
60+
34 // these functions exist in dlfcn_stubs.s and are calling C functions linked to in dlfcn_GOOS.go61 // these functions exist in dlfcn_stubs.s and are calling C functions linked to in dlfcn_GOOS.go
35 var dlopenABI0 uintptr62 var dlopenABI0 uintptr
36 var dlsymABI0 uintptr63 var dlsymABI0 uintptr
64+var dlcloseABI0 uintptr
65+var dlerrorABI0 uintptr
M dlfcn_darwin.go +2 -0
@@ -5,3 +5,5 @@ package purego
55
66 //go:cgo_import_dynamic _dlopen dlopen "/usr/lib/libSystem.B.dylib"
77 //go:cgo_import_dynamic _dlsym dlsym "/usr/lib/libSystem.B.dylib"
8+//go:cgo_import_dynamic _dlerror dlerror "/usr/lib/libSystem.B.dylib"
9+//go:cgo_import_dynamic _dlclose dlclose "/usr/lib/libSystem.B.dylib"
@@ -5,3 +5,5 @@ package purego
5 5
6 //go:cgo_import_dynamic _dlopen dlopen "/usr/lib/libSystem.B.dylib"6 //go:cgo_import_dynamic _dlopen dlopen "/usr/lib/libSystem.B.dylib"
7 //go:cgo_import_dynamic _dlsym dlsym "/usr/lib/libSystem.B.dylib"7 //go:cgo_import_dynamic _dlsym dlsym "/usr/lib/libSystem.B.dylib"
8+//go:cgo_import_dynamic _dlerror dlerror "/usr/lib/libSystem.B.dylib"
9+//go:cgo_import_dynamic _dlclose dlclose "/usr/lib/libSystem.B.dylib"
M dlfcn_stubs.s +13 -0
@@ -20,3 +20,16 @@ TEXT dlsym(SB), NOSPLIT, $0-0
2020 JMP _dlsym(SB)
2121 RET
2222
23+// func dlerror() (ret *byte)
24+GLOBL ·dlerrorABI0(SB), NOPTR|RODATA, $8
25+DATA ·dlerrorABI0(SB)/8, $dlerror(SB)
26+TEXT dlerror(SB), NOSPLIT, $0-0
27+ JMP _dlerror(SB)
28+ RET
29+
30+// func dlclose(handle uintptr) (ret int)
31+GLOBL ·dlcloseABI0(SB), NOPTR|RODATA, $8
32+DATA ·dlcloseABI0(SB)/8, $dlclose(SB)
33+TEXT dlclose(SB), NOSPLIT, $0-0
34+ JMP _dlclose(SB)
35+ RET
@@ -20,3 +20,16 @@ TEXT dlsym(SB), NOSPLIT, $0-0
20 JMP _dlsym(SB)20 JMP _dlsym(SB)
21 RET21 RET
22 22
23+// func dlerror() (ret *byte)
24+GLOBL ·dlerrorABI0(SB), NOPTR|RODATA, $8
25+DATA ·dlerrorABI0(SB)/8, $dlerror(SB)
26+TEXT dlerror(SB), NOSPLIT, $0-0
27+ JMP _dlerror(SB)
28+ RET
29+
30+// func dlclose(handle uintptr) (ret int)
31+GLOBL ·dlcloseABI0(SB), NOPTR|RODATA, $8
32+DATA ·dlcloseABI0(SB)/8, $dlclose(SB)
33+TEXT dlclose(SB), NOSPLIT, $0-0
34+ JMP _dlclose(SB)
35+ RET

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 1

Tags 102

↑↓ moveenter openesc close