Author: rpaulo
Date: Sat Jul 31 14:26:10 2010
New Revision: 210678
URL: http://svn.freebsd.org/changeset/base/210678

Log:
  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

Added:
  head/lib/librtld_db/
  head/lib/librtld_db/Makefile   (contents, props changed)
  head/lib/librtld_db/librtld_db.3   (contents, props changed)
  head/lib/librtld_db/rtld_db.c   (contents, props changed)
  head/lib/librtld_db/rtld_db.h   (contents, props changed)

Added: head/lib/librtld_db/Makefile
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ head/lib/librtld_db/Makefile        Sat Jul 31 14:26:10 2010        
(r210678)
@@ -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>

Added: head/lib/librtld_db/librtld_db.3
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ head/lib/librtld_db/librtld_db.3    Sat Jul 31 14:26:10 2010        
(r210678)
@@ -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 rpa...@freebsd.org 
+under sponsorship from the FreeBSD Foundation.

Added: head/lib/librtld_db/rtld_db.c
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ head/lib/librtld_db/rtld_db.c       Sat Jul 31 14:26:10 2010        
(r210678)
@@ -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);
+}

Added: head/lib/librtld_db/rtld_db.h
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ head/lib/librtld_db/rtld_db.h       Sat Jul 31 14:26:10 2010        
(r210678)
@@ -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_ */
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to