rd_elf.c revision d156cc9d8b05585d78e8c96d5d41f16e6471e441
/*
* 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
*/
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#include <stdlib.h>
#include <stdio.h>
#include <proc_service.h>
#include <link.h>
#include <rtld_db.h>
#include <rtld.h>
#include <alist.h>
#include <_rtld_db.h>
#include <msg.h>
#include <limits.h>
#include <string.h>
/*
* 64-bit builds are going to compile this module twice, the
* second time with _ELF64 defined. These defines should make
* all the necessary adjustments to the code.
*/
#ifdef _LP64
#ifdef _ELF64
#define _rd_event_enable32 _rd_event_enable64
#define _rd_event_getmsg32 _rd_event_getmsg64
#define _rd_get_dyns32 _rd_get_dyns64
#define _rd_get_ehdr32 _rd_get_ehdr64
#define _rd_loadobj_iter32 _rd_loadobj_iter64
#define _rd_reset32 _rd_reset64
#define find_dynamic_ent32 find_dynamic_ent64
#define validate_rdebug32 validate_rdebug64
#define MSG_SYM_BRANDOPS MSG_SYM_BRANDOPS_64
#else /* ELF32 */
#define Rtld_db_priv Rtld_db_priv32
#define MSG_SYM_BRANDOPS MSG_SYM_BRANDOPS_32
#endif /* _ELF64 */
#else /* _LP64 */
#define MSG_SYM_BRANDOPS MSG_SYM_BRANDOPS_32
#endif /* _LP64 */
/*
* BrandZ added ps_pbrandname(). Many debuggers that link directly
* against librtld_db.so may not implement this interface. Hence
* we won't call the function directly, instead we'll try to look it
* up using the linker first and only invoke it if we find it.
*/
char *, size_t);
{
return (RD_ERR);
/*
* The rtld_db_priv structure contains both the traditional (exposed)
* r_debug structure as well as private data only available to
* this library.
*/
/*
* Verify that librtld_db & rtld are at the proper revision
* levels.
*/
sizeof (Rtld_db_priv)) != PS_OK) {
return (RD_DBERR);
}
return (RD_NOCAPAB);
}
/*
* Is the image being examined from a core file or not.
* If it is a core file then the following write will fail.
*/
sizeof (Rtld_db_priv)) != PS_OK)
/*
* If this *is not* a core file then rtld_db & ld.so.1 are
* considered tightly coupled. If the versions of our private
* data structures don't match - fail!
*/
return (RD_NOCAPAB);
}
return (RD_OK);
}
{
Dyn d;
do {
PS_OK) {
return (RD_DBERR);
}
dynaddr += sizeof (d);
break;
*dyn = d;
return (RD_OK);
}
return (RD_DBERR);
}
extern char rtld_db_helper_path[MAXPATHLEN];
{
char brandname[MAXPATHLEN];
char brandlib[MAXPATHLEN];
/*
* librtld_db attempts three different methods to find
* the r_debug structure which is required to
* initialize itself. The methods are:
* method1:
* entirely independent of any text segment
* and relies on the AT_SUN_LDDATA auxvector
* to find the ld.so.1::rdebug structure.
* method2:
* lookup symbols in ld.so.1's symbol table
* to find the r_debug symbol.
* method3:
* (old dbx method) dependent upon the
* executable and not ld.so.1. We lookup the
* _DYNAMIC symbol in the executable and look for
* the DT_DEBUG entry in the .dynamic table. This
* points to rdebug.
*
* If none of that works - we fail.
*/
/*
* Method1
*
* Scan the aux vector looking for AT_BASE & AT_SUN_LDDATA
*/
}
/* LINTED */
break;
}
auxvp++;
}
}
/*
* method2 - look for r_rdebug symbol in ld.so.1
*/
/*
* If the AT_SUN_LDDATA auxv vector is not present
* fall back on doing a symlookup of
* the r_debug symbol. This is for backward
* compatiblity with older OS's
*/
} else {
}
}
/*
* method3 - find DT_DEBUG in the executables .dynamic section.
*/
return (rc);
}
return (rc);
}
return (rc);
}
}
/*
* If we are debugging a branded executable, load the appropriate
* helper library, and call its initialization routine. Being unable
* to load the helper library is not a critical error. (Hopefully
* we'll still be able to access some objects in the target.)
*/
while ((ps_pbrandname != NULL) &&
const char *isa = "";
#ifdef _LP64
#endif /* _LP64 */
if (rtld_db_helper_path[0] != '\0')
else
RTLD_LAZY | RTLD_LOCAL);
brandlib));
break;
}
brandlib));
break;
}
php);
break;
}
break;
/* NOTREACHED */
}
return (RD_DBERR);
}
return (RD_DBERR);
}
return (RD_DBERR);
}
rap->rd_tbinder = 0;
}
return (RD_OK);
}
{
return (RD_ERR);
}
return (RD_OK);
return (RD_OK);
}
/* deal with elf extended program headers */
return (RD_ERR);
return (RD_ERR);
}
return (RD_ERR);
return (RD_OK);
}
{
int i;
/* We only need to muck with dyn elements for ET_DYN objects */
return (err);
for (i = 0; i < phnum; i++) {
return (RD_ERR);
}
break;
}
if (i == phnum)
return (RD_ERR);
return (RD_ERR);
return (RD_ERR);
}
return (RD_OK);
}
{
/*
* Tell the debugged process that debugging is occuring
* This will enable the storing of event messages so that
* the can be gathered by the debugger.
*/
sizeof (Rtld_db_priv)) != PS_OK) {
return (RD_DBERR);
}
if (onoff)
else
sizeof (Rtld_db_priv)) != PS_OK) {
return (RD_DBERR);
}
return (RD_OK);
}
{
sizeof (Rtld_db_priv)) != PS_OK) {
return (RD_DBERR);
}
case RT_CONSISTENT:
break;
case RT_ADD:
break;
case RT_DELETE:
break;
}
} else
return (RD_OK);
}
{
sizeof (Rtld_db_priv)) != PS_OK) {
return (RD_DBERR);
}
/*LINTED*/
#else
#endif
sizeof (Rtld_db_priv)) != PS_OK) {
return (RD_DBERR);
}
return (RD_OK);
}
static rd_err_e
{
while (lmaddr) {
int i;
return (RD_DBERR);
}
/*
* As of 'VERSION5' we only report objects
* which have been fully relocated. While the maps
* might be in a consistent state - if a object hasn't
* been relocated - it's not really ready for the debuggers
* to examine. This is mostly due to the fact that we
* might still be mucking with the text-segment, if
* we are - we could conflict with any break-points
* the debuggers might have set.
*/
continue;
}
}
else
lobj.rl_lmident = ident;
/*
* refnameaddr is only valid from a core file
* which is VERSION3 or greater.
*/
lobj.rl_padstart = 0;
} else {
}
if (rtld_db_version >= RD_VERSION2)
if (rtld_db_version >= RD_VERSION2) {
}
if (rtld_db_version >= RD_VERSION4)
/*
* Look for beginning of data segment.
*
* NOTE: the data segment can only be found for full
* processes and not from core images.
*/
lobj.rl_data_base = 0;
lobj.rl_data_base = 0;
else {
return (RD_DBERR);
}
MSG_DB_LKMAPFAIL)));
return (RD_DBERR);
}
lobj.rl_data_base +=
break;
}
}
}
/*
* When we transfer control to the client we free the
* lock and re-atain it after we've returned from the
* client. This is to avoid any deadlock situations.
*/
*abort_iterp = 1;
break;
}
}
return (RD_OK);
}
static rd_err_e
{
client_data));
/*
* First, determine whether the link-map information has been
* established. Some debuggers have made an initial call to this
* function with a null call back function (cb), but expect a
* RD_NOMAPS error return rather than a RD_ERR return when the
* link-maps aren't available.
*/
sizeof (Rtld_db_priv)) != PS_OK) {
return (RD_DBERR);
}
return (RD_NOMAPS);
}
return (RD_DBERR);
}
return (RD_NOMAPS);
}
/*
* Having determined we have link-maps, ensure we have an iterator
* call back function.
*/
return (RD_ERR);
}
/*
* Read the initial APlist information that contains the link-map list
* entries.
*/
return (RD_DBERR);
}
/*
* Iterate through each apl.ap_data[] entry.
*/
ulong_t ident;
/*
* Obtain the Lm_list address for this apl.ap_data[] entry.
*/
return (RD_DBERR);
}
/*
* Obtain the Lm_list data for this Lm_list address.
*/
return (RD_DBERR);
}
/*
* Determine IDENT of current LM_LIST
*/
ident = LM_ID_BASE;
ident = LM_ID_LDSO;
else
return (rc);
}
if (*abort_iterp != 0)
break;
}
return (rc);
}
{
uint_t abort_iter = 0;
/* First iterate over the native target objects */
if (abort_iter != 0)
return (rc);
/* Then iterate over any branded objects. */
return (rc);
}