Home | History | Annotate | Download | only in mdb
      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 2008 Sun Microsystems, Inc.  All rights reserved.
     23  * Use is subject to license terms.
     24  */
     25 
     26 
     27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
     28 
     29 /*
     30  * Proc Service API Interposition Layer
     31  *
     32  * In order to allow multiple MDB targets to make use of librtld_db, we
     33  * provide an interposition layer for functions in the proc_service.h API
     34  * that are used by librtld_db.  Each of the functions used by librtld_db
     35  * can be conveniently expressed in terms of the MDB target API, so this
     36  * layer simply selects the appropriate target, invokes the corresponding
     37  * target API function, and then translates the error codes appropriately.
     38  * We expect that each proc_service entry point will be invoked with a
     39  * cookie (struct ps_prochandle *) which matches either a known MDB target,
     40  * or the value of a target's t->t_pshandle.  This allows us to re-vector
     41  * calls to the proc service API around libproc (which also contains an
     42  * implementation of the proc_service API) like this:
     43  *
     44  * Linker map:
     45  * +---------+   +---------+   +------------+      Legend:
     46  * |   MDB   | ->| libproc | ->| librtld_db |      <1> function in this file
     47  * +---------+   +---------+   +------------+      <2> function in libproc
     48  * ps_pread<1>   ps_pread<2>   call ps_pread() --+
     49  *                                               |
     50  * +---------------------------------------------+
     51  * |
     52  * +-> ps_pread<1>(P, ...)
     53  *       t = mdb_tgt_from_pshandle(P);
     54  *       mdb_tgt_vread(t, ...);
     55  *
     56  * If we are debugging a user process, we then make these calls (which form
     57  * the equivalent of libproc's proc_service implementation):
     58  *
     59  * mdb_tgt_vread() -> proc target t->t_vread() -> libproc.so`Pread()
     60  *
     61  * If we are debugging a user process through a kernel crash dump (kproc
     62  * target), we make these calls:
     63  *
     64  * mdb_tgt_vread() -> kproc target t->t_vread() -> mdb_tgt_aread(kvm target) ->
     65  * 	kvm target t->t_aread() -> libkvm.so`kvm_aread()
     66  *
     67  * This design allows us to support both kproc's use of librtld_db, as well
     68  * as libproc's use of librtld_db, but it does lead to one unfortunate problem
     69  * in the creation of a proc target: when the proc target invokes libproc to
     70  * construct a ps_prochandle, and libproc in turn invokes librtld_db, MDB does
     71  * not yet know what ps_prochandle has been allocated inside of libproc since
     72  * this call has not yet returned.  We also can't translate this ps_prochandle
     73  * to the target itself, since that target isn't ready to handle requests yet;
     74  * we actually need to pass the call back through to libproc.  In order to
     75  * do that, we use libdl to lookup the address of libproc's definition of the
     76  * various functions (RTLD_NEXT on the link map chain) and store these in the
     77  * ps_ops structure below.  If we ever fail to translate a ps_prochandle to
     78  * an MDB target, we simply pass the call through to libproc.
     79  */
     80 
     81 #include <proc_service.h>
     82 #include <dlfcn.h>
     83 
     84 #include <mdb/mdb_target_impl.h>
     85 #include <mdb/mdb_debug.h>
     86 #include <mdb/mdb.h>
     87 
     88 static struct {
     89 	ps_err_e (*ps_pread)(struct ps_prochandle *,
     90 	    psaddr_t, void *, size_t);
     91 	ps_err_e (*ps_pwrite)(struct ps_prochandle *,
     92 	    psaddr_t, const void *, size_t);
     93 	ps_err_e (*ps_pglobal_lookup)(struct ps_prochandle *,
     94 	    const char *, const char *, psaddr_t *);
     95 	ps_err_e (*ps_pglobal_sym)(struct ps_prochandle *P,
     96 	    const char *, const char *, ps_sym_t *);
     97 	ps_err_e (*ps_pauxv)(struct ps_prochandle *,
     98 	    const auxv_t **);
     99 	ps_err_e (*ps_pbrandname)(struct ps_prochandle *,
    100 	    char *, size_t);
    101 	ps_err_e (*ps_pdmodel)(struct ps_prochandle *,
    102 	    int *);
    103 } ps_ops;
    104 
    105 static mdb_tgt_t *
    106 mdb_tgt_from_pshandle(void *P)
    107 {
    108 	mdb_tgt_t *t;
    109 
    110 	for (t = mdb_list_next(&mdb.m_tgtlist); t; t = mdb_list_next(t)) {
    111 		if (t == P || t->t_pshandle == P)
    112 			return (t);
    113 	}
    114 
    115 	return (NULL);
    116 }
    117 
    118 /*
    119  * Read from the specified target virtual address.
    120  */
    121 ps_err_e
    122 ps_pread(struct ps_prochandle *P, psaddr_t addr, void *buf, size_t size)
    123 {
    124 	mdb_tgt_t *t = mdb_tgt_from_pshandle(P);
    125 
    126 	if (t == NULL)
    127 		return (ps_ops.ps_pread(P, addr, buf, size));
    128 
    129 	if (mdb_tgt_vread(t, buf, size, addr) != size)
    130 		return (PS_BADADDR);
    131 
    132 	return (PS_OK);
    133 }
    134 
    135 /*
    136  * Write to the specified target virtual address.
    137  */
    138 ps_err_e
    139 ps_pwrite(struct ps_prochandle *P, psaddr_t addr, const void *buf, size_t size)
    140 {
    141 	mdb_tgt_t *t = mdb_tgt_from_pshandle(P);
    142 
    143 	if (t == NULL)
    144 		return (ps_ops.ps_pwrite(P, addr, buf, size));
    145 
    146 	if (mdb_tgt_vwrite(t, buf, size, addr) != size)
    147 		return (PS_BADADDR);
    148 
    149 	return (PS_OK);
    150 }
    151 
    152 /*
    153  * Search for a symbol by name and return the corresponding address.
    154  */
    155 ps_err_e
    156 ps_pglobal_lookup(struct ps_prochandle *P, const char *object,
    157     const char *name, psaddr_t *symp)
    158 {
    159 	mdb_tgt_t *t = mdb_tgt_from_pshandle(P);
    160 	GElf_Sym sym;
    161 
    162 	if (t == NULL)
    163 		return (ps_ops.ps_pglobal_lookup(P, object, name, symp));
    164 
    165 	if (mdb_tgt_lookup_by_name(t, object, name, &sym, NULL) == 0) {
    166 		*symp = (psaddr_t)sym.st_value;
    167 		return (PS_OK);
    168 	}
    169 
    170 	return (PS_NOSYM);
    171 }
    172 
    173 /*
    174  * Search for a symbol by name and return the corresponding symbol data.
    175  * If we're compiled _LP64, we just call mdb_tgt_lookup_by_name and return
    176  * because ps_sym_t is defined to be an Elf64_Sym, which is the same as a
    177  * GElf_Sym.  In the _ILP32 case, we have to convert mdb_tgt_lookup_by_name's
    178  * result back to a ps_sym_t (which is an Elf32_Sym).
    179  */
    180 ps_err_e
    181 ps_pglobal_sym(struct ps_prochandle *P, const char *object,
    182     const char *name, ps_sym_t *symp)
    183 {
    184 	mdb_tgt_t *t = mdb_tgt_from_pshandle(P);
    185 #if defined(_ILP32)
    186 	GElf_Sym sym;
    187 
    188 	if (t == NULL)
    189 		return (ps_ops.ps_pglobal_sym(P, object, name, symp));
    190 
    191 	if (mdb_tgt_lookup_by_name(t, object, name, &sym, NULL) == 0) {
    192 		symp->st_name = (Elf32_Word)sym.st_name;
    193 		symp->st_value = (Elf32_Addr)sym.st_value;
    194 		symp->st_size = (Elf32_Word)sym.st_size;
    195 		symp->st_info = ELF32_ST_INFO(
    196 		    GELF_ST_BIND(sym.st_info), GELF_ST_TYPE(sym.st_info));
    197 		symp->st_other = sym.st_other;
    198 		symp->st_shndx = sym.st_shndx;
    199 		return (PS_OK);
    200 	}
    201 
    202 #elif defined(_LP64)
    203 	if (t == NULL)
    204 		return (ps_ops.ps_pglobal_sym(P, object, name, symp));
    205 
    206 	if (mdb_tgt_lookup_by_name(t, object, name, symp, NULL) == 0)
    207 		return (PS_OK);
    208 #endif
    209 
    210 	return (PS_NOSYM);
    211 }
    212 
    213 /*
    214  * Report a debug message.  We allow proc_service API clients to report
    215  * messages via our debug stream if the MDB_DBG_PSVC token is enabled.
    216  */
    217 void
    218 ps_plog(const char *format, ...)
    219 {
    220 	va_list alist;
    221 
    222 	va_start(alist, format);
    223 	mdb_dvprintf(MDB_DBG_PSVC, format, alist);
    224 	va_end(alist);
    225 }
    226 
    227 /*
    228  * Return the auxv structure from the process being examined.
    229  */
    230 ps_err_e
    231 ps_pauxv(struct ps_prochandle *P, const auxv_t **auxvp)
    232 {
    233 	mdb_tgt_t *t = mdb_tgt_from_pshandle(P);
    234 
    235 	if (t == NULL)
    236 		return (ps_ops.ps_pauxv(P, auxvp));
    237 
    238 	if (mdb_tgt_auxv(t, auxvp) != 0)
    239 		return (PS_ERR);
    240 
    241 	return (PS_OK);
    242 }
    243 
    244 ps_err_e
    245 ps_pbrandname(struct ps_prochandle *P, char *buf, size_t len)
    246 {
    247 	mdb_tgt_t *t = mdb_tgt_from_pshandle(P);
    248 	const auxv_t *auxv;
    249 
    250 	if (t == NULL)
    251 		return (ps_ops.ps_pbrandname(P, buf, len));
    252 
    253 	if (mdb_tgt_auxv(t, &auxv) != 0)
    254 		return (PS_ERR);
    255 
    256 	while (auxv->a_type != AT_NULL) {
    257 		if (auxv->a_type == AT_SUN_BRANDNAME)
    258 			break;
    259 		auxv++;
    260 	}
    261 	if (auxv->a_type == AT_NULL)
    262 		return (PS_ERR);
    263 
    264 	if (mdb_tgt_readstr(t, MDB_TGT_AS_VIRT,
    265 	    buf, len, auxv->a_un.a_val) <= 0)
    266 		return (PS_ERR);
    267 
    268 	return (PS_OK);
    269 }
    270 
    271 /*
    272  * Return the data model of the target.
    273  */
    274 ps_err_e
    275 ps_pdmodel(struct ps_prochandle *P, int *dm)
    276 {
    277 	mdb_tgt_t *t = mdb_tgt_from_pshandle(P);
    278 
    279 	if (t == NULL)
    280 		return (ps_ops.ps_pdmodel(P, dm));
    281 
    282 	switch (mdb_tgt_dmodel(t)) {
    283 	case MDB_TGT_MODEL_LP64:
    284 		*dm = PR_MODEL_LP64;
    285 		return (PS_OK);
    286 	case MDB_TGT_MODEL_ILP32:
    287 		*dm = PR_MODEL_ILP32;
    288 		return (PS_OK);
    289 	}
    290 
    291 	return (PS_ERR);
    292 }
    293 
    294 /*
    295  * Stub function in case we cannot find the necessary symbols from libproc.
    296  */
    297 static ps_err_e
    298 ps_fail(struct ps_prochandle *P)
    299 {
    300 	mdb_dprintf(MDB_DBG_PSVC, "failing call to pshandle %p\n", (void *)P);
    301 	return (PS_BADPID);
    302 }
    303 
    304 /*
    305  * Initialization function for the proc service interposition layer: we use
    306  * libdl to look up the next definition of each function in the link map.
    307  */
    308 void
    309 mdb_pservice_init(void)
    310 {
    311 	if ((ps_ops.ps_pread = (ps_err_e (*)())
    312 	    dlsym(RTLD_NEXT, "ps_pread")) == NULL)
    313 		ps_ops.ps_pread = (ps_err_e (*)())ps_fail;
    314 
    315 	if ((ps_ops.ps_pwrite = (ps_err_e (*)())
    316 	    dlsym(RTLD_NEXT, "ps_pwrite")) == NULL)
    317 		ps_ops.ps_pwrite = (ps_err_e (*)())ps_fail;
    318 
    319 	if ((ps_ops.ps_pglobal_lookup = (ps_err_e (*)())
    320 	    dlsym(RTLD_NEXT, "ps_pglobal_lookup")) == NULL)
    321 		ps_ops.ps_pglobal_lookup = (ps_err_e (*)())ps_fail;
    322 
    323 	if ((ps_ops.ps_pglobal_sym = (ps_err_e (*)())
    324 	    dlsym(RTLD_NEXT, "ps_pglobal_sym")) == NULL)
    325 		ps_ops.ps_pglobal_sym = (ps_err_e (*)())ps_fail;
    326 
    327 	if ((ps_ops.ps_pauxv = (ps_err_e (*)())
    328 	    dlsym(RTLD_NEXT, "ps_pauxv")) == NULL)
    329 		ps_ops.ps_pauxv = (ps_err_e (*)())ps_fail;
    330 
    331 	if ((ps_ops.ps_pbrandname = (ps_err_e (*)())
    332 	    dlsym(RTLD_NEXT, "ps_pbrandname")) == NULL)
    333 		ps_ops.ps_pbrandname = (ps_err_e (*)())ps_fail;
    334 
    335 	if ((ps_ops.ps_pdmodel = (ps_err_e (*)())
    336 	    dlsym(RTLD_NEXT, "ps_pdmodel")) == NULL)
    337 		ps_ops.ps_pdmodel = (ps_err_e (*)())ps_fail;
    338 }
    339