rainycape / dl Goto Github PK
View Code? Open in Web Editor NEWRuntime dynamic library loader (dlopen / dlsym) for Go (golang)
License: Mozilla Public License 2.0
Runtime dynamic library loader (dlopen / dlsym) for Go (golang)
License: Mozilla Public License 2.0
I made a mistake in an application that caused select() (from libc) to get called in a tight loop. To my surprise, I got:
runtime: writebarrierptr *0xc42039c8a0 = 0x2
fatal error: bad pointer in write barrier
runtime stack:
runtime.throw(0x4d1430, 0x1c)
/home/soren/lib/go/go/src/runtime/panic.go:605 +0x95
runtime.writebarrierptr.func1()
/home/soren/lib/go/go/src/runtime/mbarrier.go:213 +0xbd
runtime.systemstack(0xc420026600)
/home/soren/lib/go/go/src/runtime/asm_amd64.s:344 +0x79
runtime.mstart()
/home/soren/lib/go/go/src/runtime/proc.go:1135
goroutine 1 [running]:
runtime.systemstack_switch()
/home/soren/lib/go/go/src/runtime/asm_amd64.s:298 fp=0xc42003fb08 sp=0xc42003fb00 pc=0x450c50
runtime.writebarrierptr(0xc42039c8a0, 0x2)
/home/soren/lib/go/go/src/runtime/mbarrier.go:211 +0x8d fp=0xc42003fb40 sp=0xc42003fb08 pc=0x41143d
github.com/rainycape/dl.makeTrampoline.func1(0xc42039e000, 0x5, 0x5, 0x0, 0x0, 0x0)
/home/soren/src/go/src/github.com/rainycape/dl/trampoline.go:74 +0x866 fp=0xc42003fd60 sp=0xc42003fb40 pc=0x499626
reflect.callReflect(0xc42000c0a0, 0xc42003ff20)
/home/soren/lib/go/go/src/reflect/value.go:514 +0x38b fp=0xc42003ff00 sp=0xc42003fd60 pc=0x47f78b
reflect.makeFuncStub(0x2, 0x0, 0x1294770, 0x0, 0x0, 0x1, 0x1, 0x1294770, 0x4ac600, 0xc420392f60, ...)
/home/soren/lib/go/go/src/reflect/asm_amd64.s:17 +0x33 fp=0xc42003ff20 sp=0xc42003ff00 pc=0x4851c3
main.main()
/home/soren/src/go/src/dlfailuretest/main.go:27 +0xad fp=0xc42003ff80 sp=0xc42003ff20 pc=0x49b22d
runtime.main()
/home/soren/lib/go/go/src/runtime/proc.go:195 +0x226 fp=0xc42003ffe0 sp=0xc42003ff80 pc=0x42aa36
runtime.goexit()
/home/soren/lib/go/go/src/runtime/asm_amd64.s:2337 +0x1 fp=0xc42003ffe8 sp=0xc42003ffe0 pc=0x453311
This happens after MANY calls to select(), so it's very racy.
trampoline.go:74 is where the first argument to select() is being added to the args array. mbarrier.go is a bit over my head, but if I'm guessing correctly, the fact that that first argument (which was C.int(2) in my case) is being passed along as unsafe.Pointer (to satisfy the void** type make_call expects), causes something in Go to get upset, because 2 is not a valid pointer value.
If I disable garbage collection, it never seems to happen, fwiw.
At any rate, it does seem fair that an unsafe.Pointer(2) is indeed considered problematic. It's not just unsafe. It's invalid.
Here's how you can reproduce it:
package main
import "log"
import "github.com/rainycape/dl"
// #include <sys/select.h>
// void setFd(int fd, fd_set *fds) {
// FD_SET(fd, fds);
// }
import "C"
var oldSelect func(nfds C.int, readfds, writefds, exceptfds *C.fd_set, timeval *C.struct_timeval) int
func loadOldFunc(sym string, f interface{}) {
lib, err := dl.Open("libc", 0)
if err != nil {
log.Fatalln(err)
}
defer lib.Close()
lib.Sym(sym, f)
}
func main() {
loadOldFunc("select", &oldSelect)
writefds := (*C.fd_set)(C.malloc(C.sizeof_fd_set))
C.setFd(C.int(0), writefds)
for {
seenFds := oldSelect(C.int(2), (*C.fd_set)(nil), writefds, (*C.fd_set)(nil), (*C.struct_timeval)(nil))
log.Printf("%v", seenFds)
}
}
how to use the C structure to like func(data C.VERSION) to dl?
C code:
typedef struct VERSION {
char modelVersion[MAX_LENGTH];
char sdkVersion[MAX_LENGTH];
} VERSION;
want go code like:
f := func(data *C.VERSION) int
client.Sym("GetVersion", &f)
when I execute go get gopkgs.com/dl.v1
, returns package gopkgs.com/dl.v1: unrecognized import path "gopkgs.com/dl.v1"
and when I visit gopkgs.com
on browser, the page shows 502 Bad Gateway
,could you fix that ?thanks
axet@debian:~/source/github/desktop/go/test$ go version
go version go1.4.2 linux/386
axet@debian:~/source/github/desktop/go/test$ go get github.com/rainycape/dl
# github.com/rainycape/dl
/tmp/go-build651627590/github.com/rainycape/dl/_obj/amd64.o: In function `call':
../../../../go/src/github.com/rainycape/dl/amd64.c:56: undefined reference to `make_call'
collect2: error: ld returned 1 exit status
axet@debian:~/source/github/desktop/go/test$
compile a LD_PRELOAD so using following code
//export fork
func fork() C.pid_t {
lib, err := dl.Open("libc", 0)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
defer lib.Close()
var old_fork func() C.pid_t
lib.Sym("fork", &old_fork)
return old_fork()
}
run command
# LD_PRELOAD=`pwd`/libshellhook.so bash
panic: reflect.MakeFunc: value of type int32 is not assignable to type main._Ctype_int
goroutine 17 [running, locked to thread]:
reflect.Value.assignTo(0x7f61b5cfda60, 0xc00001808c, 0x85, 0x7f61b5ac9ec4, 0x10, 0x7f61b5cfdc60, 0xc000042df0, 0x7f61b5a8ac25, 0x7f61b5ac7a20, 0xc000042cf8)
/usr/local/go/src/reflect/value.go:2435 +0x405
reflect.callReflect(0xc00006a2d0, 0xc000042df0, 0xc000042dd8)
/usr/local/go/src/reflect/value.go:600 +0x4b9
reflect.makeFuncStub(0xc000046280, 0x7f61b5ac7f3b, 0x4, 0x7f61b5cf9180, 0xc000010030, 0x0, 0x0, 0x0, 0x0, 0xc000046280, ...)
/usr/local/go/src/reflect/asm_amd64.s:20 +0x44
main.fork(0x0)
/work/golib/main.go:83 +0x149
main._cgoexpwrap_032d238aa31d_fork(0x77c3a0)
_cgo_gotypes.go:85 +0x25
A Feature Request To Add 32 Bit Architecture For DL, Currently Can't Compile A Project With DL in a 32 Bit Debian Machine.
Compiling 'src/main.go' into 'build'
github.com/rainycape/dl
# github.com/rainycape/dl
/usr/bin/ld: $WORK/b065/_x004.o: in function `call':
../../go/pkg/mod/github.com/rainycape/[email protected]/amd64.c:56: undefined reference to `make_call'
collect2: error: ld returned 1 exit status
Hello,
I've been playing around with your library and so far love it. I am interested in what you see your plans are with respect to the idea of JIT compiliation so as to remove the reflect overhead.
I would love to help out on this task in whatever way possible, both because it would help the performance of the library I am making, and it just sounds like an interesting problem to solve.
/opt/homebrew/Cellar/go/1.19.3/libexec/pkg/tool/darwin_arm64/link: running clang failed: exit status 1
Undefined symbols for architecture arm64:
"_make_call", referenced from:
_call in 000003.o
ld: symbol(s) not found for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
hi,
testing github.com/rainycape/dl
with go-1.6, I get:
$> go test -v ./...
--- FAIL: TestFunctions (0.00s)
panic: runtime error: cgo argument has Go pointer to Go pointer [recovered]
panic: runtime error: cgo argument has Go pointer to Go pointer
I just go get -u github.com/rainycape/dl
, then use dl.Open in simple code. but I got undefined: dl.Open
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.