1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 #include <dlfcn.h> 29 #include <link.h> 30 #include <pthread.h> 31 #include <assert.h> 32 33 #include <fm/topo_mod.h> 34 35 #include <topo_error.h> 36 #include <topo_alloc.h> 37 #include <topo_subr.h> 38 39 typedef struct topo_rtld { 40 void *rtld_dlp; /* libdl(3DL) handle for shared library */ 41 int (*rtld_init)(topo_mod_t *); /* shared library's _topo_init() */ 42 void (*rtld_fini)(topo_mod_t *); /* shared library's _topo_fini() */ 43 } topo_rtld_t; 44 45 static int 46 rtld_fini(topo_mod_t *mod) 47 { 48 topo_rtld_t *rp = mod->tm_data; 49 50 assert(mod != NULL); 51 52 if (mod->tm_flags & TOPO_MOD_REG) { 53 rp->rtld_fini(mod); 54 if (mod->tm_flags & TOPO_MOD_REG) { 55 topo_mod_unregister(mod); 56 } 57 } 58 59 if (getenv("TOPONODLCLOSE") == NULL) 60 (void) dlclose(rp->rtld_dlp); 61 topo_mod_free(mod, rp, sizeof (topo_rtld_t)); 62 63 return (0); 64 } 65 66 static int 67 rtld_init(topo_mod_t *mod) 68 { 69 int err; 70 topo_rtld_t *rp; 71 void *dlp; 72 73 if ((dlp = dlopen(mod->tm_path, RTLD_LOCAL | RTLD_NOW)) == NULL) { 74 topo_dprintf(TOPO_DBG_ERR, 75 "dlopen() failed: %s\n", dlerror()); 76 return (topo_mod_seterrno(mod, ETOPO_RTLD_OPEN)); 77 } 78 79 if ((rp = mod->tm_data = topo_mod_alloc(mod, sizeof (topo_rtld_t))) 80 == NULL) 81 return (topo_mod_seterrno(mod, ETOPO_RTLD_OPEN)); 82 83 rp->rtld_dlp = dlp; 84 rp->rtld_init = (int (*)())dlsym(dlp, "_topo_init"); 85 rp->rtld_fini = (void (*)())dlsym(dlp, "_topo_fini"); 86 87 if (rp->rtld_init == NULL) { 88 (void) dlclose(dlp); 89 topo_free(rp, sizeof (topo_rtld_t)); 90 return (topo_mod_seterrno(mod, ETOPO_RTLD_INIT)); 91 } 92 93 /* 94 * Call _topo_init() in the module. 95 */ 96 err = rp->rtld_init(mod); 97 98 if (err < 0 || !(mod->tm_flags & TOPO_MOD_REG)) { 99 (void) rtld_fini(mod); 100 return (topo_mod_seterrno(mod, ETOPO_MOD_NOREG)); 101 } 102 103 return (0); 104 } 105 106 const topo_modops_t topo_rtld_ops = { 107 rtld_init, 108 rtld_fini, 109 }; 110