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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright (c) 2001 by Sun Microsystems, Inc. 24 * All rights reserved. 25 */ 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 #include <stdio.h> 29 #include <dlfcn.h> 30 #include <libelf.h> 31 #include <link.h> 32 #include "debug.h" 33 #include "msg.h" 34 #include "_libld.h" 35 36 37 38 /* 39 * Table which defines the default functions to be called by the library 40 * SUPPORT (-S <libname>). These functions can be redefined by the 41 * ld_support_loadso() routine. 42 */ 43 static Support_list support[LDS_NUM] = { 44 {MSG_ORIG(MSG_SUP_VERSION), { 0, 0 }}, /* LDS_VERSION */ 45 {MSG_ORIG(MSG_SUP_INPUT_DONE), { 0, 0 }}, /* LDS_INPUT_DONE */ 46 #ifdef _ELF64 47 {MSG_ORIG(MSG_SUP_START_64), { 0, 0 }}, /* LDS_START64 */ 48 {MSG_ORIG(MSG_SUP_ATEXIT_64), { 0, 0 }}, /* LDS_ATEXIT64 */ 49 {MSG_ORIG(MSG_SUP_FILE_64), { 0, 0 }}, /* LDS_FILE64 */ 50 {MSG_ORIG(MSG_SUP_INP_SECTION_64), { 0, 0 }}, /* LDS_INP_SECTION64 */ 51 {MSG_ORIG(MSG_SUP_SECTION_64), { 0, 0 }} /* LDS_SECTION64 */ 52 #else /* Elf32 */ 53 {MSG_ORIG(MSG_SUP_START), { 0, 0 }}, /* LDS_START */ 54 {MSG_ORIG(MSG_SUP_ATEXIT), { 0, 0 }}, /* LDS_ATEXIT */ 55 {MSG_ORIG(MSG_SUP_FILE), { 0, 0 }}, /* LDS_FILE */ 56 {MSG_ORIG(MSG_SUP_INP_SECTION), { 0, 0 }}, /* LDS_INP_SECTION */ 57 {MSG_ORIG(MSG_SUP_SECTION), { 0, 0 }} /* LDS_SECTION */ 58 #endif 59 }; 60 61 /* 62 * Loads in a support shared object specified using the SGS_SUPPORT environment 63 * variable or the -S ld option, and determines which interface functions are 64 * provided by that object. 65 * 66 * return values for ld_support_loadso: 67 * 1 - shared object loaded sucessfully 68 * S_ERROR - aww, damn! 69 */ 70 uintptr_t 71 ld_support_loadso(const char *obj) 72 { 73 void *handle; 74 void (*fptr)(); 75 Func_list *flp; 76 int i; 77 uint_t ver_level; 78 79 /* 80 * Load the required support library. If we are unable to load it fail 81 * with a fatal error. 82 */ 83 if ((handle = dlopen(obj, RTLD_LAZY)) == NULL) { 84 eprintf(ERR_FATAL, MSG_INTL(MSG_SUP_NOLOAD), obj, dlerror()); 85 return (S_ERROR); 86 } 87 88 ver_level = LD_SUP_VERSION1; 89 for (i = 0; i < LDS_NUM; i++) { 90 if (fptr = (void (*)())dlsym(handle, support[i].sup_name)) { 91 92 if ((flp = (Func_list *) 93 libld_malloc(sizeof (Func_list))) == NULL) 94 return (S_ERROR); 95 96 flp->fl_obj = obj; 97 flp->fl_fptr = fptr; 98 DBG_CALL(Dbg_support_load(obj, support[i].sup_name)); 99 if (i == LDS_VERSION) { 100 DBG_CALL(Dbg_support_action(flp->fl_obj, 101 support[LDS_VERSION].sup_name, 102 LDS_VERSION, 0)); 103 ver_level = ((uint_t(*)()) 104 flp->fl_fptr)(LD_SUP_VCURRENT); 105 if ((ver_level == LD_SUP_VNONE) || 106 (ver_level > LD_SUP_VCURRENT)) { 107 eprintf(ERR_FATAL, 108 MSG_INTL(MSG_SUP_BADVERSION), 109 LD_SUP_VCURRENT, 110 ver_level); 111 (void) dlclose(handle); 112 return (S_ERROR); 113 } 114 115 } 116 flp->fl_version = ver_level; 117 if (list_appendc(&support[i].sup_funcs, flp) == 0) 118 return (S_ERROR); 119 } 120 } 121 return (1); 122 } 123 124 125 /* 126 * Wrapper routines for the ld support library calls. 127 */ 128 void 129 lds_start(const char *ofile, const Half etype, const char *caller) 130 { 131 Func_list *flp; 132 Listnode *lnp; 133 134 for (LIST_TRAVERSE(&support[LDS_START].sup_funcs, lnp, flp)) { 135 DBG_CALL(Dbg_support_action(flp->fl_obj, 136 support[LDS_START].sup_name, LDS_START, ofile)); 137 (*flp->fl_fptr)(ofile, etype, caller); 138 } 139 } 140 141 142 void 143 lds_atexit(int exit_code) 144 { 145 Func_list *flp; 146 Listnode *lnp; 147 148 for (LIST_TRAVERSE(&support[LDS_ATEXIT].sup_funcs, lnp, flp)) { 149 DBG_CALL(Dbg_support_action(flp->fl_obj, 150 support[LDS_ATEXIT].sup_name, LDS_ATEXIT, 0)); 151 (*flp->fl_fptr)(exit_code); 152 } 153 } 154 155 156 void 157 lds_file(const char *ifile, const Elf_Kind ekind, int flags, Elf *elf) 158 { 159 Func_list *flp; 160 Listnode *lnp; 161 162 for (LIST_TRAVERSE(&support[LDS_FILE].sup_funcs, lnp, flp)) { 163 int _flags = 0; 164 165 if (!(flags & FLG_IF_CMDLINE)) 166 _flags |= LD_SUP_DERIVED; 167 if (!(flags & FLG_IF_NEEDED)) 168 _flags |= LD_SUP_INHERITED; 169 if (flags & FLG_IF_EXTRACT) 170 _flags |= LD_SUP_EXTRACTED; 171 172 DBG_CALL(Dbg_support_action(flp->fl_obj, 173 support[LDS_FILE].sup_name, LDS_FILE, ifile)); 174 (*flp->fl_fptr)(ifile, ekind, _flags, elf); 175 } 176 } 177 178 uintptr_t 179 lds_input_section(const char *scnname, Shdr **shdr, Word ndx, 180 const char *file, Elf_Scn *scn, Elf *elf, Ofl_desc *ofl) 181 { 182 Func_list *flp; 183 Listnode *lnp; 184 uint_t flags = 0; 185 Elf_Data *data = NULL; 186 187 for (LIST_TRAVERSE(&support[LDS_INP_SECTION].sup_funcs, lnp, flp)) { 188 /* 189 * This interface was introduced in VERSION2 - so only 190 * call it for libraries reporting support for 191 * version 2 or above. 192 */ 193 if (flp->fl_version < LD_SUP_VERSION2) 194 continue; 195 if ((data == NULL) && 196 ((data = elf_getdata(scn, NULL)) == NULL)) { 197 eprintf(ERR_ELF, MSG_INTL(MSG_ELF_GETDATA), 198 file); 199 ofl->ofl_flags |= FLG_OF_FATAL; 200 return (S_ERROR); 201 } 202 203 DBG_CALL(Dbg_support_action(flp->fl_obj, 204 support[LDS_INP_SECTION].sup_name, LDS_INP_SECTION, 205 scnname)); 206 (*flp->fl_fptr)(scnname, shdr, ndx, data, elf, &flags); 207 } 208 return (0); 209 } 210 211 void 212 lds_section(const char *scn, Shdr *shdr, Word ndx, 213 Elf_Data *data, Elf *elf) 214 { 215 Func_list *flp; 216 Listnode *lnp; 217 218 for (LIST_TRAVERSE(&support[LDS_SECTION].sup_funcs, lnp, flp)) { 219 DBG_CALL(Dbg_support_action(flp->fl_obj, 220 support[LDS_SECTION].sup_name, LDS_SECTION, scn)); 221 (*flp->fl_fptr)(scn, shdr, ndx, data, elf); 222 } 223 } 224 225 void 226 lds_input_done(void) 227 { 228 Func_list *flp; 229 Listnode *lnp; 230 uint_t flags = 0; 231 232 for (LIST_TRAVERSE(&support[LDS_INPUT_DONE].sup_funcs, lnp, flp)) { 233 /* 234 * This interface was introduced in VERSION2 - so only 235 * call it for libraries reporting support for 236 * version 2 or above. 237 */ 238 if (flp->fl_version < LD_SUP_VERSION2) 239 continue; 240 DBG_CALL(Dbg_support_action(flp->fl_obj, 241 support[LDS_INPUT_DONE].sup_name, LDS_INPUT_DONE, 0)); 242 (*flp->fl_fptr)(&flags); 243 } 244 } 245