/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
*/
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <libproc.h>
#include <proc_service.h>
#include <synch.h>
#include <rtld_db.h>
/*
* ATTENTION:
* Librtl_db brand plugin libraries should NOT directly invoke any
* libproc.so interfaces or be linked against libproc. If a librtl_db
* brand plugin library uses libproc.so interfaces then it may break
* any other librtld_db consumers (like mdb) that tries to attach
* to a branded process. The only safe interfaces that the a librtld_db
* brand plugin library can use to access a target process are the
* proc_service(3PROC) apis.
*/
/*
* M_DATA comes from some streams header file but is also redifined in
* _rtld_db.h, so nuke the old streams definition here.
*/
#ifdef M_DATA
#endif /* M_DATA */
/*
* For 32-bit versions of this library, this file get's compiled once.
* For 64-bit versions of this library, this file get's compiled twice,
* once with _ELF64 defined and once without. The expectation is that
* the 64-bit version of the library can properly deal with both 32-bit
* and 64-bit elf files, hence in the 64-bit library there are two copies
* of all the interfaces in this file, one set named *32 and one named *64.
*
* This also means that we need to be careful when declaring local pointers
* that point to objects in another processes address space, since these
* pointers may not match the current processes pointer width. Basically,
* we should not use any objects that change size between 32 and 64 bit
* modes like: long, void *, uintprt_t, caddr_t, psaddr_t, size_t, etc.
* Instead we should declare all pointers as uint32_t. Then when we
* are compiled to deal with 64-bit targets we'll re-define uing32_t
* to be a uint64_t.
*/
#ifdef _LP64
#ifdef _ELF64
#endif /* _ELF64 */
#endif /* _LP64 */
#include <_rtld_db.h>
/*ARGSUSED*/
static rd_helper_data_t
{
return (NULL);
}
/*ARGSUSED*/
static void
{
}
/*ARGSUSED*/
static int
{
return (RD_OK);
}
/*ARGSUSED*/
static rd_err_e
{
*dynpp_sz = 0;
return (RD_OK);
}
};
static uint32_t
{
return ((uint32_t)-1);
auxvp++;
}
return ((uint32_t)-1);
}
/*
* Normally, the native Solaris librtldb_db plugin uses a bunch of different
* methods to try and find the rdebug structure associated with the target
* process we're debugging. For details on the different methods see
* _rd_reset32(). Thankfully our job is easier. We know that the brand
* library is always linked against the native linker, and when the
* process was first executed we saved off a pointer to the brand linkers
* rdebug structure in one of our brand specific aux vectors,
* AT_SUN_BRAND_COMMON_LDDATA. So we'll just look that up here.
*/
/*ARGSUSED*/
static rd_helper_data_t
{
int rd_dmodel;
ps_plog("brand_ldb_init: lookup of data model failed");
return (NULL);
}
#ifdef _ELF64
#else /* !_ELF64 */
#endif /* !_ELF64 */
ps_plog("brand_ldb_init: no LDDATA found in aux vector");
return (NULL);
}
"at: 0x%p", lddata_addr);
/*
* Ok. So this is kinda ugly. Basically we know that we're going to
* be parsing data from link maps that are generated by a Solaris
* linker. As it turns out, that's exactly what the default
* Solaris librtld_db library is designed to do. So rather than
* duplicate all that link map parsing code here we'll simply
* invoke the native librtld_db that normally does this, and when
* we do we'll point them at our emulation libraries link map.
*
* Of course these interfacess aren't really public interfaces
* and they take a "struct rd_agent" as a parameter. So here
* we'll allocate and initialize a new "struct rd_agent", point
* it at our emulation libraries link map, and initialize just
* enough of the structure to make the librtld_db interfaces
* that we want to use happy.
*/
ps_plog("brand_ldb_init: can't allocate memory");
return (NULL);
}
/*
* When we get invoked from librtld_db, and we call back into it,
* librtld_db will once again check if there is a plugin and
* invoke it. Since we don't want to enter a recursive loop
* we're going to specify a different plugin interface for
* our linkmap, and these new plugin interfaces won't actually
* do anything other than return.
*/
/*
* validate_rdebug32() requires the following "struct rd_agent"
* members to be initialized:
* rd_psp, rd_rdebug
*
* validate_rdebug32() initializes the following "struct rd_agent"
* members:
* rd_flags, rd_rdebugvers, rd_rtlddbpriv
*/
ps_plog("brand_ldb_init: can't find valid r_debug data");
return (NULL);
}
return ((rd_helper_data_t)rap_new);
}
static void
{
ps_plog("brand_ldb_fini: cleaning up brand helper");
}
/*ARGSUSED*/
static int
{
int err;
/*
* _rd_loadobj_iter32() requires the following "struct rd_agent"
* members to be initialized:
* rd_rtlddbpriv, rd_rdebugvers, rd_flags,
* rd_helper.rh_ops, rd_dmodel
*/
return (err);
}
/*ARGSUSED*/
static rd_err_e
{
int err;
return (err);
}
/*
* Librtld_db plugin linkage struct.
*
* When we get loaded by librtld_db, it will look for the symbol below
* to find our plugin entry points.
*/
};