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