1// 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} 83