erl_unix_sys_ddll.c
来自「OTP是开放电信平台的简称」· C语言 代码 · 共 306 行
C
306 行
/* ``The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in * compliance with the License. You should have received a copy of the * Erlang Public License along with this software. If not, it can be * retrieved via the world wide web at http://www.erlang.org/. * * Software distributed under the License is distributed on an "AS IS" * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See * the License for the specific language governing rights and limitations * under the License. * * The Initial Developer of the Original Code is Ericsson Utvecklings AB. * Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings * AB. All Rights Reserved.'' * * $Id$ *//* * Interface functions to the dynamic linker using dl* functions. * (As far as I know it works on SunOS 4, 5, Linux and FreeBSD. /Seb) */#ifdef HAVE_CONFIG_H# include "config.h"#endif#include "sys.h"#include "erl_vm.h"#include "global.h"#ifdef HAVE_DLFCN_H#include <dlfcn.h>#endif#ifdef HAVE_MACH_O_DYLD_H#include <mach-o/dyld.h>#endif/* some systems do not have RTLD_NOW defined, and require the "mode" * argument to dload() always be 1. */#ifndef RTLD_NOW# define RTLD_NOW 1#endif#define MAX_NAME_LEN 255 /* XXX should we get the system path size? */#define EXT_LEN 3#define FILE_EXT ".so" /* extension appended to the filename */#if !defined(HAVE_MACH_O_DYLD_H)static char **errcodes = NULL;static int num_errcodes = 0;static int num_errcodes_allocated = 0;static char *my_strdup(char *what){ char *res = erts_alloc(ERTS_ALC_T_DDLL_ERRCODES, strlen(what) + 1); strcpy(res, what); return res;}static int find_errcode(char *string) { int i; for(i=0;i<num_errcodes;++i) { if (!strcmp(string, errcodes[i])) { return i; } } if (num_errcodes_allocated == num_errcodes) { errcodes = (num_errcodes_allocated == 0) ? erts_alloc(ERTS_ALC_T_DDLL_ERRCODES, (num_errcodes_allocated = 10) * sizeof(char *)) : erts_realloc(ERTS_ALC_T_DDLL_ERRCODES, errcodes, (num_errcodes_allocated += 10) * sizeof(char *)); } errcodes[num_errcodes++] = my_strdup(string); return (num_errcodes - 1);}#endifvoid erl_sys_ddll_init(void) {#if defined(HAVE_DLOPEN) && defined(ERTS_NEED_DLOPEN_BEFORE_DLERROR) /* * dlopen() needs to be called before we make the first call to * dlerror(); otherwise, dlerror() might dump core. At least * some versions of linuxthread suffer from this bug. */ void *handle = dlopen("/nonexistinglib", RTLD_NOW); if (handle) dlclose(handle);#endif return;}/* * Open a shared object */int erts_sys_ddll_open(char *full_name, void **handle){ int ret;#if defined(HAVE_DLOPEN) || defined(HAVE_MACH_O_DYLD_H) char dlname[MAX_NAME_LEN+EXT_LEN+1]; int len; ret = 0; if ((len = sys_strlen(full_name)) >= MAX_NAME_LEN) { ret = ERL_DE_LOAD_ERROR_NAME_TO_LONG; goto done; } sys_strcpy(dlname, full_name); sys_strcpy(dlname+len, FILE_EXT);#if defined(HAVE_MACH_O_DYLD_H) /* XXX:PaN Reentrant interface? */ { int result; NSObjectFileImage ofile; result = NSCreateObjectFileImageFromFile(dlname, &ofile); switch (result) { case NSObjectFileImageSuccess: *handle = NSLinkModule(ofile, dlname, NSLINKMODULE_OPTION_PRIVATE); if ((*handle)) { ret = ERL_DE_NO_ERROR; } else { ret = ERL_DE_ERROR_UNSPECIFIED; } break; /* XXX:PaN should anything return something else ? */ /*case NSObjectFileImageInappropriateFile: case NSObjectFileImageArch: case NSObjectFileImageFormat: case NSObjectFileImageAccess: case NSObjectFileImageFailure: */ default: ret = ERL_DE_DYNAMIC_ERROR_OFFSET - result; break; } goto done; }#else { char *str; dlerror(); *handle = dlopen(dlname, RTLD_NOW); if ((str = dlerror()) == NULL) { ret = ERL_DE_NO_ERROR; } else { /* Remove prefix filename to avoid exploading number of errorcodes on extreme usage */ if (strstr(str,dlname) == str) { char *save_str = str; str += strlen(dlname); while (*str == ':' || *str == ' ') { ++str; } if (*str == '\0') { /* Better with filename than nothing... */ str = save_str; } } ret = ERL_DE_DYNAMIC_ERROR_OFFSET - find_errcode(str); } goto done; }#endif#else ret = ERL_DE_ERROR_NO_DDLL_FUNCTIONALITY; goto done;#endif done: return ret;}/* * Find a symbol in the shared object */int erts_sys_ddll_sym(void *handle, char *func_name, void **function){#if defined(HAVE_MACH_O_DYLD_H) { NSSymbol nssymbol = NSLookupSymbolInModule((NSModule)handle,func_name); if (nssymbol == NULL) { return ERL_DE_LOOKUP_ERROR_NOT_FOUND; } *function = NSAddressOfSymbol(nssymbol); return ERL_DE_NO_ERROR; }#elif defined(HAVE_DLOPEN) { void *sym; char *e; int ret; dlerror(); sym = dlsym(handle, func_name); if ((e = dlerror()) != NULL) { ret = ERL_DE_DYNAMIC_ERROR_OFFSET - find_errcode(e); } else { *function = sym; ret = ERL_DE_NO_ERROR; } return ret; }#else return ERL_DE_ERROR_NO_DDLL_FUNCTIONALITY;#endif}/* XXX:PaN These two will be changed with new driver interface! *//* * Load the driver init function, might appear under different names depending on object arch... */int erts_sys_ddll_load_driver_init(void *handle, void **function){ void *fn; int res; if ((res = erts_sys_ddll_sym(handle, "driver_init", &fn)) != ERL_DE_NO_ERROR) { res = erts_sys_ddll_sym(handle, "_driver_init", &fn); } if (res == ERL_DE_NO_ERROR) { *function = fn; } return res;}/* * Call the driver_init function, whatever it's really called, simple on unix... */void *erts_sys_ddll_call_init(void *function) { void *(*initfn)(void) = function; return (*initfn)();}/* * Close a chared object */int erts_sys_ddll_close(void *handle){#if defined(HAVE_MACH_O_DYLD_H) return ERL_DE_NO_ERROR; /* XXX:PaN No close functionality in MacOSX??? */#elif defined(HAVE_DLOPEN) { int ret; char *s; dlerror(); if (dlclose(handle) == 0) { ret = ERL_DE_NO_ERROR; } else { if ((s = dlerror()) == NULL) { ret = ERL_DE_ERROR_UNSPECIFIED; } else { ret = ERL_DE_DYNAMIC_ERROR_OFFSET - find_errcode(s); } } return ret; }#else return ERL_DE_ERROR_NO_DDLL_FUNCTIONALITY;#endif}/* * Return string that describes the (current) error */char *erts_sys_ddll_error(int code){ int actual_code; if (code > ERL_DE_DYNAMIC_ERROR_OFFSET) { return "Unspecified error"; } actual_code = -1*(code - ERL_DE_DYNAMIC_ERROR_OFFSET);#if defined(HAVE_MACH_O_DYLD_H) switch (actual_code) { case NSObjectFileImageFailure: return "General dynamic load failure"; case NSObjectFileImageInappropriateFile: return "Driver is an inappropriate Mach-O file"; case NSObjectFileImageArch: return "Driver is compiled for inappropriate Mach-O architecture"; case NSObjectFileImageFormat: return "Driver Mach-O file format is invalid"; case NSObjectFileImageAccess: return "Access error loading driver Mach-O file"; default: return "Unknown Mach-O error"; }#elif defined(HAVE_DLOPEN) { char *msg; if (actual_code >= num_errcodes) { msg = "Unknown dlload error"; } else { msg = errcodes[actual_code]; } return msg; }#endif return "no error";}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?