blob: 23774f612e0f4030865e14c106c0fd815c3e7fe3 [file] [log] [blame]
khenaidooffe076b2019-01-15 16:08:08 -05001// Copyright 2016 CoreOS, Inc.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15// Package dlopen provides some convenience functions to dlopen a library and
16// get its symbols.
17package dlopen
18
19// #cgo LDFLAGS: -ldl
20// #include <stdlib.h>
21// #include <dlfcn.h>
22import "C"
23import (
24 "errors"
25 "fmt"
26 "unsafe"
27)
28
29var ErrSoNotFound = errors.New("unable to open a handle to the library")
30
31// LibHandle represents an open handle to a library (.so)
32type LibHandle struct {
33 Handle unsafe.Pointer
34 Libname string
35}
36
37// GetHandle tries to get a handle to a library (.so), attempting to access it
38// by the names specified in libs and returning the first that is successfully
39// opened. Callers are responsible for closing the handler. If no library can
40// be successfully opened, an error is returned.
41func GetHandle(libs []string) (*LibHandle, error) {
42 for _, name := range libs {
43 libname := C.CString(name)
44 defer C.free(unsafe.Pointer(libname))
45 handle := C.dlopen(libname, C.RTLD_LAZY)
46 if handle != nil {
47 h := &LibHandle{
48 Handle: handle,
49 Libname: name,
50 }
51 return h, nil
52 }
53 }
54 return nil, ErrSoNotFound
55}
56
57// GetSymbolPointer takes a symbol name and returns a pointer to the symbol.
58func (l *LibHandle) GetSymbolPointer(symbol string) (unsafe.Pointer, error) {
59 sym := C.CString(symbol)
60 defer C.free(unsafe.Pointer(sym))
61
62 C.dlerror()
63 p := C.dlsym(l.Handle, sym)
64 e := C.dlerror()
65 if e != nil {
66 return nil, fmt.Errorf("error resolving symbol %q: %v", symbol, errors.New(C.GoString(e)))
67 }
68
69 return p, nil
70}
71
72// Close closes a LibHandle.
73func (l *LibHandle) Close() error {
74 C.dlerror()
75 C.dlclose(l.Handle)
76 e := C.dlerror()
77 if e != nil {
78 return fmt.Errorf("error closing %v: %v", l.Libname, errors.New(C.GoString(e)))
79 }
80
81 return nil
82}