obpsym.c revision 1048:e29b523f29b4
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/* 24 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 25 * Use is subject to license terms. 26 */ 27 28#pragma ident "%Z%%M% %I% %E% SMI" 29 30/* 31 * This module supports callbacks from the firmware 32 * such that address and name lookups can work and use kernel symbol names. 33 * For example "ctrace" will provide symbolic names, if they are available. 34 * Also, normal firmware name to address lookups should work, though be 35 * careful with clashing kernel names, such as "startup" and "reset" which 36 * may be the firmware names and *not* the kernel names. 37 * 38 * The module locks the symbol tables in memory, when it's installed, 39 * and unlocks them when it is removed. To install the module, you 40 * may either add "set obpdebug=1" to /etc/system or just modload it. 41 * 42 * This file contains the actual code the does the lookups, and interfaces 43 * with the kernel kobj stuff. The transfer of data and control to/from 44 * the firmware is handled in prom-dependent code. 45 */ 46 47#include <sys/types.h> 48#include <sys/param.h> 49#include <sys/systm.h> 50#include <sys/debug.h> 51#include <sys/errno.h> 52#include <sys/modctl.h> 53#include <sys/kobj.h> 54#include <sys/promif.h> 55#include <sys/ddi.h> 56#include <sys/sunddi.h> 57#include <sys/reboot.h> 58#include <sys/callb.h> 59 60int obpsym_debug = 0; 61#define DPRINTF(str) if (obpsym_debug) prom_printf(str) 62#define DPRINTF1(str, a) if (obpsym_debug) prom_printf(str, a); 63#define DPRINTF2(str, a, b) if (obpsym_debug) prom_printf(str, a, b); 64#define DXPRINTF if (obpsym_debug > 1) prom_printf 65 66int obpheld = 1; /* Prevents unloading when set */ 67extern int obpdebug; 68 69/* 70 * name_to_value - translate a string into an address 71 * 72 * The string may be one of two forms - 'symname' or 'modname:symname'. 73 * (We also accept 'unix:symname' as a synonymn for 'symname'.) 74 * The latter form causes a kobj_lookup() to occur only in the given module, 75 * the former causes a kobj_getsymvalue() on the entire kernel symbol table. 76 * 77 * mod_lock locking is not needed for the &modules list because 78 * modctl structures are never unlinked from the &modules list. 79 */ 80int 81name_to_value(char *name, uintptr_t *value) 82{ 83 register char *symname = name; 84 register char *modname = ""; 85 char *p; 86 int retval = 0; 87 uintptr_t symvalue = 0; 88 char c = (char)0; 89 90 /* 91 * we take names of the form: "modname:symbol", "unix:symbol", "symbol" 92 */ 93 if ((p = strchr(name, ':')) != NULL && p[1] != (char)0) { 94 symname = p + 1; 95 modname = name; 96 c = *p; 97 *p = (char)0; 98 } 99 100 if (*modname == (char)0) { 101 symvalue = kobj_getsymvalue(symname, 0); 102 } else { 103 struct modctl *mp = &modules; 104 105 do { 106 if (strcmp(modname, mp->mod_modname) == 0) { 107 symvalue = kobj_lookup(mp->mod_mp, symname); 108 break; 109 } 110 } while ((mp = mp->mod_next) != &modules); 111 } 112 113 if (symvalue == 0) 114 retval = -1; 115 if (c != (char)0) /* Restore incoming cstr */ 116 *p = c; 117 118 *value = symvalue; 119 return (retval); 120} 121 122/* 123 * value_to_name - translate an address into a string + offset 124 * 125 * mod_lock locking is not needed fro the modules list because 126 * modctl structures are never unlinked from the &modules list. 127 */ 128ulong_t 129value_to_name(uintptr_t value, char *symbol) 130{ 131 struct modctl *modp = &modules; 132 ulong_t offset; 133 char *name; 134 135 DPRINTF1("value_to_name: Looking for %p\n", (void *)value); 136 137 do { 138 if (modp->mod_mp && 139 (name = kobj_searchsym(modp->mod_mp, value, &offset))) { 140 (void) strcpy(symbol, modp->mod_modname); 141 (void) strcat(symbol, ":"); 142 (void) strcat(symbol, name); 143 return (offset); 144 } 145 } while ((modp = modp->mod_next) != &modules); 146 147 *symbol = (char)0; 148 return ((ulong_t)-1l); 149} 150 151/* 152 * loadable module wrapper 153 */ 154static struct modlmisc modlmisc = { 155 &mod_miscops, "OBP symbol callbacks %I%" 156}; 157 158static struct modlinkage modlinkage = { 159 MODREV_1, (void *)&modlmisc, NULL 160}; 161 162/*ARGSUSED*/ 163static boolean_t 164reset_callbacks(void *arg, int code) 165{ 166 extern void set_sym_callbacks(); 167 168 if (code == CB_CODE_CPR_RESUME) 169 set_sym_callbacks(); 170 return (B_TRUE); 171} 172 173int 174_init(void) 175{ 176 int retval; 177 extern int install_callbacks(void); 178 extern void remove_callbacks(void); 179 180 if (install_callbacks() != 0) 181 return (ENXIO); 182 183 obpdebug = 1; 184 185 if (boothowto & RB_HALT) 186 debug_enter("obpsym: halt flag (-h) is set.\n"); 187 188 retval = mod_install(&modlinkage); 189 190 /* 191 * if load fails remove callback and unlock symbols 192 */ 193 if (retval) { 194 printf("obpsym: Error %d installing OBP syms module\n", retval); 195 remove_callbacks(); 196 obpdebug = 0; 197 } 198 else 199 (void) callb_add(reset_callbacks, 0, CB_CL_CPR_OBP, "obpsym"); 200 201 return (retval); 202} 203 204int 205_fini(void) 206{ 207 int retval; 208 extern void remove_callbacks(void); 209 210 if (obpheld != 0) 211 return (EBUSY); 212 213 retval = mod_remove(&modlinkage); 214 215 /* 216 * if unload succeeds remove callback and unlock symbols 217 */ 218 if (retval == 0) { 219 remove_callbacks(); 220 obpdebug = 0; 221 } 222 return (retval); 223} 224 225int 226_info(struct modinfo *modinfop) 227{ 228 return (mod_info(&modlinkage, modinfop)); 229} 230