Debugger Interface Agents
An agent provides an opaque handle that can describe internal interface structures. The agent also provides a mechanism of communication between the exported and imported interfaces. The rtld-debugger interface is intended to be used by a debugger which can manipulate several processes at the same time, these agents are used to identify the process.
- struct ps_prochandle
Is an opaque structure that is created by the controlling process to identify the target process that is passed between the exported and imported interface.
- struct rd_agent
Is an opaque structure created by the rtld-debugger interface that identifies the target process that is passed between the exported and imported interface.
Debugger Exported Interface
This section describes the various interfaces exported by the /usr/lib/librtld_db.so.1 audit library. It is broken down into functional groups.
Agent Manipulation Interfaces
- rd_init()
This function establishes the rtld-debugger version requirements. The base version is defined as RD_VERSION1. The current version is always defined by RD_VERSION.
rd_err_e rd_init(int version);
Version RD_VERSION2, added in Solaris 8 10/00, extends the rd_loadobj_t structure. See the rl_flags, rl_bend and rl_dynamic fields in "Scanning Loadable Objects".
Version RD_VERSION3, added in Solaris 8 01/01, extends the rd_plt_info_t structure. See the pi_baddr and pi_flags fields in "Procedure Linkage Table Skipping".
If the version requirement of the controlling process is greater than the rtld-debugger interface available, then RD_NOCAPAB is returned.
- rd_new()
This function creates a new exported interface agent.
rd_agent_t * rd_new(struct ps_prochandle * php);
php is a cookie created by the controlling process to identify the target process. This cookie is used by the imported interface offered by the controlling process to maintain context, and is opaque to the rtld-debugger interface.
- rd_reset()
This function resets the information within the agent based off the same ps_prochandle structure given to rd_new().
rd_err_e rd_reset(struct rd_agent * rdap);
- rd_delete()
This function deletes an agent and frees any state associated with it.
void rd_delete(struct rd_agent * rdap);
Error Handling
The following error states can be returned by the rtld-debugger interface (defined in rtld_db.h):
typedef enum { RD_ERR, RD_OK, RD_NOCAPAB, RD_DBERR, RD_NOBASE, RD_NODYNAM, RD_NOMAPS } rd_err_e; |
The following interfaces can be used to gather the error information.
- rd_errstr()
This function returns a descriptive error string describing the error code rderr.
char * rd_errstr(rd_err_e rderr);
- rd_log()
This function turns logging on (1) or off (0).
void rd_log(const int onoff);
When logging is turned on, the imported interface function ps_plog() provided by the controlling process, is called with more detailed diagnostic information.
Scanning Loadable Objects
You can obtain information for each object maintained on the runtime linkers link-map is achieved by using the following structure, defined in rtld_db.h:
typedef struct rd_loadobj { psaddr_t rl_nameaddr; unsigned rl_flags; psaddr_t rl_base; psaddr_t rl_data_base; unsigned rl_lmident; psaddr_t rl_refnameaddr; psaddr_t rl_plt_base; unsigned rl_plt_size; psaddr_t rl_bend; psaddr_t rl_padstart; psaddr_t rl_padend; psaddt_t rl_dynamic; } rd_loadobj_t; |
Notice that all addresses given in this structure, including string pointers, are addresses in the target process and not in the address space of the controlling process itself.
- rl_nameaddr
A pointer to a string that contains the name of the dynamic object.
- rl_flags
With revision RD_VERSION2, dynamically loaded relocatable objects are identified with RD_FLG_MEM_OBJECT.
- rl_base
The base address of the dynamic object.
- rl_data_base
The base address of the data segment of the dynamic object.
- rl_lmident
The link-map identifier (see "Establishing a Namespace").
- rl_refnameaddr
If the dynamic object is a filter, then this points to the name of the filtees.
- rl_plt_base, rl_plt_size
These elements are present for backward compatibility and are currently unused.
- rl_bend
The end address of the object (text + data + bss). With revision RD_VERSION2, a dynamically loaded relocatable object will cause this element to point to the end of the created object, which will include its section headers.
- rl_padstart
The base address of the padding before the dynamic object (refer to "Dynamic Object Padding").
- rl_padend
The base address of the padding after the dynamic object (refer to "Dynamic Object Padding").
- rl_dynamic
This field, added with RD_VERSION2, provides the base address of the object's dynamic section, which allows reference to such entries as DT_CHECKSUM (see Table 7-42).
The rd_loadobj_iter() routine uses this object data structure to access information from the runtime linker's link-map lists:
- rd_loadobj_iter()
This function iterates over all dynamic objects currently loaded in the target process.
typedef int rl_iter_f(const rd_loadobj_t *, void *); rd_err_e rd_loadobj_iter(rd_agent_t * rap, rl_iter_f * cb, void * clnt_data);
On each iteration the imported function specified by cb is called. clnt_data can be used to pass data to the cb call. Information about each object is returned via a pointer to a volatile (stack allocated) rd_loadobj_t structure.
Return codes from the cb routine are examined by rd_loadobj_iter() and have the following meaning:
1 - continue processing link-maps.
0 - stop processing link-maps and return control to the controlling process.
rd_loadobj_iter() returns RD_OK on success. A return of RD_NOMAPS indicates the runtime linker has not yet loaded the initial link-maps.