summaryrefslogtreecommitdiffstats
path: root/lib/librtld_db
diff options
context:
space:
mode:
authorrpaulo <rpaulo@FreeBSD.org>2010-07-31 14:26:10 +0000
committerrpaulo <rpaulo@FreeBSD.org>2010-07-31 14:26:10 +0000
commit27277244cd333006d5d010f8047d83a3a8a402c1 (patch)
treeef3df8ba55e73337ce46c4ed406e22517fdf8b3c /lib/librtld_db
parent0ccd4521f0bf896c3176bea8d48fb1f02d4c45de (diff)
downloadFreeBSD-src-27277244cd333006d5d010f8047d83a3a8a402c1.zip
FreeBSD-src-27277244cd333006d5d010f8047d83a3a8a402c1.tar.gz
Import the librtld_db library. This is needed by userland DTrace.
This is not yet enabled in the build because I also need to import a new version of libproc. Sponsored by: The FreeBSD Foundation
Diffstat (limited to 'lib/librtld_db')
-rw-r--r--lib/librtld_db/Makefile14
-rw-r--r--lib/librtld_db/librtld_db.3191
-rw-r--r--lib/librtld_db/rtld_db.c226
-rw-r--r--lib/librtld_db/rtld_db.h150
4 files changed, 581 insertions, 0 deletions
diff --git a/lib/librtld_db/Makefile b/lib/librtld_db/Makefile
new file mode 100644
index 0000000..efaed62
--- /dev/null
+++ b/lib/librtld_db/Makefile
@@ -0,0 +1,14 @@
+# $FreeBSD$
+
+.include <bsd.own.mk>
+
+LIB= rtld_db
+SHLIB_MAJOR= 1
+MAN= librtld_db.3
+
+SRCS= rtld_db.c
+INCS= rtld_db.h
+
+CFLAGS+= -I${.CURDIR}
+
+.include <bsd.lib.mk>
diff --git a/lib/librtld_db/librtld_db.3 b/lib/librtld_db/librtld_db.3
new file mode 100644
index 0000000..339f0d4
--- /dev/null
+++ b/lib/librtld_db/librtld_db.3
@@ -0,0 +1,191 @@
+.\"-
+.\" Copyright (c) 2010 The FreeBSD Foundation
+.\" All rights reserved.
+.\"
+.\" This software was developed by Rui Paulo under sponsorship from
+.\" the FreeBSD Foundation.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd June 10, 2010
+.Dt LIBRTLD_DB 3
+.Os
+.Sh NAME
+.Nm librtld_db
+.Nd library for run-time linker debugging
+.Sh LIBRARY
+.Lb librtld_db
+.Sh SYNOPSIS
+.In rtld_db.h
+.Ft void
+.Fo rd_delete
+.Fa "rd_agent_t *rdap"
+.Fc
+.Ft char *
+.Fo rd_errstr
+.Fa "rd_err_e rderr"
+.Fc
+.Ft rd_err_e
+.Fo rd_event_addr
+.Fa "rd_agent_t *rdap, rd_notify_t *notify"
+.Fc
+.Ft rd_err_e
+.Fo rd_event_enable
+.Fa "rd_agent_t *rdap, int onoff"
+.Fc
+.Ft rd_err_e
+.Fo rd_event_getmsg
+.Fa "rd_agent_t *rdap, rd_event_msg_t *msg"
+.Fc
+.Ft rd_err_e
+.Fo rd_init
+.Fa "int version"
+.Fc
+.Ft typedef int
+.Fo rl_iter_f
+.Fa "const rd_loadobj_t *, void *"
+.Fc
+.Ft rd_err_e
+.Fo rd_loadobj_iter
+.Fa "rd_agent_t *rdap, rl_iter_f *cb, void *clnt_data"
+.Fc
+.Ft void
+.Fo rd_log
+.Fa "const int onoff"
+.Fc
+.Ft rd_agent_t *
+.Fo rd_new
+.Fa "struct proc_handle *php"
+.Fc
+.Ft rd_err_e
+.Fo rd_objpad_enable
+.Fa "rd_agent_t *rdap, size_t padsize"
+.Fc
+.Ft rd_err_e
+.Fo rd_plt_resolution
+.Fa "rd_agent_t *rdap, uintptr_t pc, struct proc *proc
+.Fa "uintptr_t plt_base, rd_plt_info_t *rpi"
+.Fc
+.Ft rd_err_e
+.Fo rd_reset
+.Fa "rd_agent_t *rdap"
+.Fc
+.Sh DESCRIPTION
+The
+.Nm librtld_db
+library provides a debugging interface to the run-time linker (rtld).
+This library must be used along with
+.Xr libproc 3 .
+.Pp
+Most library functions take a
+.Ft rd_agent_t
+argument.
+This argument is an opaque structure containing information associated with
+the current status of the agent.
+.Pp
+Before you start using
+.Nm
+you should call
+.Fn rd_init
+with the
+.Ft RD_VERSION
+argument.
+This initializes the library to the correct version your program was compiled
+with and provides proper ABI stability.
+.Pp
+What follows is a description of what each function.
+.Pp
+.Fn rd_new
+creates a new
+.Nm
+agent.
+The
+.Ft php
+argument should be the
+.Ft proc_handle
+you received from
+.Xr libproc 3 .
+.Pp
+.Fn rd_reset
+resets your previously created agent.
+.Pp
+.Fn rd_delete
+dealocates the resources associated with the agent.
+.Pp
+.Fn rd_errstr
+returns an error string describing the error present in
+.Ft rderr .
+.Pp
+.Fn rd_event_enable
+enables reporting of events.
+This function always returns RD_OK.
+.Pp
+.Fn rd_event_addr
+returns the event address in the
+.Ft event
+paramenter.
+At the moment we only report RD_NOTIFY_BPT events.
+.Pp
+.Fn rd_event_getmsg
+returns the message assoicated wit hthe latest event.
+At the moment only RD_POSTINIT events are supported.
+.Pp
+.Fn rd_loadobj_iter
+allows you to iterate over the program's loaded objects.
+.Ft cb
+is a callback of type
+.Fn rl_iter_f .
+.Sh RETURN VALUES
+Most functions return an
+.Ft rd_err_e
+type error.
+The error codes are described in the header file for this library.
+You can get the error string using
+.Fn rd_errstr .
+.Sh CAVEATS
+The functions
+.Fn rd_event_enable ,
+.Fn rd_log ,
+.Fn rd_objpad_enable
+and
+.Fn rd_plt_resolution
+are not yet implemented.
+.Sh SEE ALSO
+.Xr ld 1 ,
+.Xr ld-elf.so.1 1 ,
+.Xr ld.so 1 ,
+.Xr libproc 3 ,
+.Xr rtld 1
+.Sh HISTORY
+The
+.Nm librtld_db
+library first appeared in
+.Fx 9.0
+and was modeled after the same library present in the Solaris operating system.
+.Sh AUTHORS
+The
+.Nm librtld_db
+library and this manual page were written by
+.An Rui Paulo Aq rpaulo@FreeBSD.org
+under sponsorship from the FreeBSD Foundation.
diff --git a/lib/librtld_db/rtld_db.c b/lib/librtld_db/rtld_db.c
new file mode 100644
index 0000000..fef8d46
--- /dev/null
+++ b/lib/librtld_db/rtld_db.c
@@ -0,0 +1,226 @@
+/*
+ * Copyright (c) 2010 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * This software was developed by Rui Paulo under sponsorship from the
+ * FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <machine/_inttypes.h>
+#include <sys/types.h>
+#include <sys/user.h>
+
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include <libproc.h>
+#include <libutil.h>
+
+#include "rtld_db.h"
+
+static int _librtld_db_debug = 0;
+#define DPRINTF(...) do { \
+ if (_librtld_db_debug) { \
+ fprintf(stderr, "librtld_db: DEBUG: "); \
+ fprintf(stderr, __VA_ARGS__); \
+ } \
+} while (0)
+
+void
+rd_delete(rd_agent_t *rdap)
+{
+
+ free(rdap);
+}
+
+const char *
+rd_errstr(rd_err_e rderr)
+{
+
+ switch (rderr) {
+ case RD_ERR:
+ return "generic error";
+ case RD_OK:
+ return "no error";
+ case RD_NOCAPAB:
+ return "capability not supported";
+ case RD_DBERR:
+ return "database error";
+ case RD_NOBASE:
+ return "NOBASE";
+ case RD_NOMAPS:
+ return "NOMAPS";
+ default:
+ return "unknown error";
+ }
+}
+
+rd_err_e
+rd_event_addr(rd_agent_t *rdap, rd_event_e event __unused, rd_notify_t *notify)
+{
+ DPRINTF("%s rdap %p notify %p\n", __func__, rdap, notify);
+
+ notify->type = RD_NOTIFY_BPT;
+ notify->u.bptaddr = rdap->rda_addr;
+
+ return (RD_OK);
+}
+
+rd_err_e
+rd_event_enable(rd_agent_t *rdap __unused, int onoff)
+{
+ DPRINTF("%s onoff %d\n", __func__, onoff);
+
+ return (RD_OK);
+}
+
+rd_err_e
+rd_event_getmsg(rd_agent_t *rdap __unused, rd_event_msg_t *msg)
+{
+ DPRINTF("%s\n", __func__);
+
+ msg->type = RD_POSTINIT;
+ msg->u.state = RD_CONSISTENT;
+
+ return (RD_OK);
+}
+
+rd_err_e
+rd_init(int version)
+{
+ char *debug = NULL;
+
+ if (version == RD_VERSION) {
+ debug = getenv("LIBRTLD_DB_DEBUG");
+ _librtld_db_debug = debug ? atoi(debug) : 0;
+ return (RD_OK);
+ } else
+ return (RD_NOCAPAB);
+}
+
+rd_err_e
+rd_loadobj_iter(rd_agent_t *rdap, rl_iter_f *cb, void *clnt_data)
+{
+ int cnt, i, lastvn = 0;
+ rd_loadobj_t rdl;
+ struct kinfo_vmentry *kves, *kve;
+
+ DPRINTF("%s\n", __func__);
+
+ if ((kves = kinfo_getvmmap(proc_getpid(rdap->rda_php), &cnt)) == NULL) {
+ warn("ERROR: kinfo_getvmmap() failed");
+ return (RD_ERR);
+ }
+ for (i = 0; i < cnt; i++) {
+ kve = kves + i;
+ if (kve->kve_type == KVME_TYPE_VNODE)
+ lastvn = i;
+ memset(&rdl, 0, sizeof(rdl));
+ /*
+ * Map the kinfo_vmentry struct to the rd_loadobj structure.
+ */
+ rdl.rdl_saddr = kve->kve_start;
+ rdl.rdl_eaddr = kve->kve_end;
+ rdl.rdl_offset = kve->kve_offset;
+ if (kve->kve_protection & KVME_PROT_READ)
+ rdl.rdl_prot |= RD_RDL_R;
+ if (kve->kve_protection & KVME_PROT_WRITE)
+ rdl.rdl_prot |= RD_RDL_W;
+ if (kve->kve_protection & KVME_PROT_EXEC)
+ rdl.rdl_prot |= RD_RDL_X;
+ strlcpy(rdl.rdl_path, kves[lastvn].kve_path,
+ sizeof(rdl.rdl_path));
+ (*cb)(&rdl, clnt_data);
+ }
+ free(kves);
+
+ return (RD_OK);
+}
+
+void
+rd_log(const int onoff)
+{
+ DPRINTF("%s\n", __func__);
+
+ (void)onoff;
+}
+
+rd_agent_t *
+rd_new(struct proc_handle *php)
+{
+ rd_agent_t *rdap;
+
+ rdap = malloc(sizeof(rd_agent_t));
+ if (rdap) {
+ memset(rdap, 0, sizeof(rd_agent_t));
+ rdap->rda_php = php;
+ rd_reset(rdap);
+ }
+
+ return (rdap);
+}
+
+rd_err_e
+rd_objpad_enable(rd_agent_t *rdap, size_t padsize)
+{
+ DPRINTF("%s\n", __func__);
+
+ (void)rdap;
+ (void)padsize;
+
+ return (RD_ERR);
+}
+
+rd_err_e
+rd_plt_resolution(rd_agent_t *rdap, uintptr_t pc, struct proc *proc,
+ uintptr_t plt_base, rd_plt_info_t *rpi)
+{
+ DPRINTF("%s\n", __func__);
+
+ (void)rdap;
+ (void)pc;
+ (void)proc;
+ (void)plt_base;
+ (void)rpi;
+
+ return (RD_ERR);
+}
+
+rd_err_e
+rd_reset(rd_agent_t *rdap)
+{
+ GElf_Sym sym;
+
+ if (proc_name2sym(rdap->rda_php, "ld-elf.so.1", "r_debug_state",
+ &sym) < 0)
+ return (RD_ERR);
+ DPRINTF("found r_debug_state at 0x%lx\n", (unsigned long)sym.st_value);
+ rdap->rda_addr = sym.st_value;
+
+ return (RD_OK);
+}
diff --git a/lib/librtld_db/rtld_db.h b/lib/librtld_db/rtld_db.h
new file mode 100644
index 0000000..33da4d3
--- /dev/null
+++ b/lib/librtld_db/rtld_db.h
@@ -0,0 +1,150 @@
+/*
+ * Copyright (c) 2010 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * This software was developed by Rui Paulo under sponsorship from the
+ * FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _RTLD_DB_H_
+#define _RTLD_DB_H_
+
+#include <sys/param.h>
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+
+#define RD_VERSION 1
+
+typedef enum {
+ RD_OK,
+ RD_ERR,
+ RD_DBERR,
+ RD_NOCAPAB,
+ RD_NODYNAM,
+ RD_NOBASE,
+ RD_NOMAPS
+} rd_err_e;
+
+typedef struct rd_agent {
+ struct proc_handle *rda_php;
+ uintptr_t rda_addr; /* address of r_debug_state */
+} rd_agent_t;
+
+typedef struct rd_loadobj {
+ uintptr_t rdl_saddr; /* start address */
+ uintptr_t rdl_eaddr; /* end address */
+ uint32_t rdl_offset;
+ uint8_t rdl_prot;
+#define RD_RDL_R 0x01
+#define RD_RDL_W 0x02
+#define RD_RDL_X 0x04
+ enum {
+ RDL_TYPE_NONE = 0,
+ RDL_TYPE_DEF,
+ RDL_TYPE_VNODE,
+ RDL_TYPE_SWAP,
+ RDL_TYPE_DEV,
+ /* XXX some types missing */
+ RDL_TYPE_UNKNOWN = 255
+ } rdl_type;
+ unsigned char rdl_path[PATH_MAX];
+} rd_loadobj_t;
+
+typedef enum {
+ RD_NONE = 0,
+ RD_PREINIT,
+ RD_POSTINIT,
+ RD_DLACTIVITY
+} rd_event_e;
+
+typedef enum {
+ RD_NOTIFY_BPT,
+ RD_NOTIFY_AUTOBPT,
+ RD_NOTIFY_SYSCALL
+} rd_notify_e;
+
+typedef struct rd_notify {
+ rd_notify_e type;
+ union {
+ uintptr_t bptaddr;
+ long syscallno;
+ } u;
+} rd_notify_t;
+
+typedef enum {
+ RD_NOSTATE = 0,
+ RD_CONSISTENT,
+ RD_ADD,
+ RD_DELETE
+} rd_state_e;
+
+typedef struct rd_event_msg {
+ rd_event_e type;
+ union {
+ rd_state_e state;
+ } u;
+} rd_event_msg_t;
+
+typedef enum {
+ RD_RESOLVE_NONE,
+ RD_RESOLVE_STEP,
+ RD_RESOLVE_TARGET,
+ RD_RESOLVE_TARGET_STEP
+} rd_skip_e;
+
+typedef struct rd_plt_info {
+ rd_skip_e pi_skip_method;
+ long pi_nstep;
+ uintptr_t pi_target;
+ uintptr_t pi_baddr;
+ unsigned int pi_flags;
+} rd_plt_info_t;
+
+#define RD_FLG_PI_PLTBOUND 0x0001
+
+__BEGIN_DECLS
+
+struct proc_handle;
+void rd_delete(rd_agent_t *);
+const char *rd_errstr(rd_err_e);
+rd_err_e rd_event_addr(rd_agent_t *, rd_event_e, rd_notify_t *);
+rd_err_e rd_event_enable(rd_agent_t *, int);
+rd_err_e rd_event_getmsg(rd_agent_t *, rd_event_msg_t *);
+rd_err_e rd_init(int);
+typedef int rl_iter_f(const rd_loadobj_t *, void *);
+rd_err_e rd_loadobj_iter(rd_agent_t *, rl_iter_f *, void *);
+void rd_log(const int);
+rd_agent_t *rd_new(struct proc_handle *);
+rd_err_e rd_objpad_enable(rd_agent_t *, size_t);
+struct proc;
+rd_err_e rd_plt_resolution(rd_agent_t *, uintptr_t, struct proc *,
+ uintptr_t, rd_plt_info_t *);
+rd_err_e rd_reset(rd_agent_t *);
+
+__END_DECLS
+
+#endif /* _RTLD_DB_H_ */
OpenPOWER on IntegriCloud