Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys DTrace: Add support for CTF sections in the netbsd elf i...
details: https://anonhg.NetBSD.org/src/rev/2da15793b3a9
branches: trunk
changeset: 752951:2da15793b3a9
user: darran <darran%NetBSD.org@localhost>
date: Fri Mar 12 21:43:10 2010 +0000
description:
DTrace: Add support for CTF sections in the netbsd elf image, load these
at boot.
Add a ksyms_mod_foreach() function to iterate a callback function over the
set of elf symbols for a specific module (netbsd included).
Add kern_ctf.c and mod_ctf_get() to allow the retrieval and decompression
of CTF sections for a specific module.
diffstat:
sys/conf/files | 3 +-
sys/kern/kern_ctf.c | 229 +++++++++++++++++++++++++++++++++++++++++
sys/kern/kern_ksyms.c | 200 ++++++++++++++++++++++++++++++++++-
sys/lib/libsa/loadfile_elf32.c | 64 ++++++++++-
sys/sys/kern_ctf.h | 53 +++++++++
sys/sys/ksyms.h | 10 +-
6 files changed, 545 insertions(+), 14 deletions(-)
diffs (truncated from 808 to 300 lines):
diff -r 1cae04d0440a -r 2da15793b3a9 sys/conf/files
--- a/sys/conf/files Fri Mar 12 21:37:37 2010 +0000
+++ b/sys/conf/files Fri Mar 12 21:43:10 2010 +0000
@@ -1,4 +1,4 @@
-# $NetBSD: files,v 1.980 2010/03/03 13:39:57 tsutsui Exp $
+# $NetBSD: files,v 1.981 2010/03/12 21:43:11 darran Exp $
# @(#)files.newconf 7.5 (Berkeley) 5/10/93
version 20090313
@@ -1424,6 +1424,7 @@
file kern/kern_condvar.c
file kern/kern_core.c coredump
file kern/kern_cpu.c
+file kern/kern_ctf.c
file kern/kern_descrip.c
file kern/kern_event.c
file kern/kern_exec.c
diff -r 1cae04d0440a -r 2da15793b3a9 sys/kern/kern_ctf.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/sys/kern/kern_ctf.c Fri Mar 12 21:43:10 2010 +0000
@@ -0,0 +1,229 @@
+/* $NetBSD: kern_ctf.c,v 1.1 2010/03/12 21:43:11 darran Exp $ */
+/*-
+ * Copyright (c) 2008 John Birrell <jb%freebsd.org@localhost>
+ * All rights reserved.
+ *
+ * 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: src/sys/kern/kern_ctf.c,v 1.1.4.1 2009/08/03 08:13:06 kensmith Exp $
+ */
+
+#define ELFSIZE ARCH_ELFSIZE
+#include <sys/module.h>
+#include <sys/exec_elf.h>
+#include <sys/kmem.h>
+#include <sys/malloc.h>
+#include <sys/kobj_impl.h>
+#include <sys/kobj.h>
+#include <sys/kern_ctf.h>
+
+#define _KSYMS_PRIVATE
+#include <sys/ksyms.h>
+
+#include <net/zlib.h>
+
+/*
+ * Note this file is included by both link_elf.c and link_elf_obj.c.
+ *
+ * The CTF header structure definition can't be used here because it's
+ * (annoyingly) covered by the CDDL. We will just use a few bytes from
+ * it as an integer array where we 'know' what they mean.
+ */
+#define CTF_HDR_SIZE 36
+#define CTF_HDR_STRTAB_U32 7
+#define CTF_HDR_STRLEN_U32 8
+
+static void *
+z_alloc(void *nil, u_int items, u_int size)
+{
+ void *ptr;
+
+ ptr = malloc(items * size, M_TEMP, M_NOWAIT);
+ return ptr;
+}
+
+static void
+z_free(void *nil, void *ptr)
+{
+ free(ptr, M_TEMP);
+}
+
+int
+mod_ctf_get(struct module *mod, mod_ctf_t *mc)
+{
+ mod_ctf_t *cmc;
+ struct ksyms_symtab *st;
+ void * ctftab = NULL;
+ size_t sz;
+ int error = 0;
+ int compressed = 0;
+
+ void *ctfbuf = NULL;
+ uint8_t *ctfaddr;
+ size_t ctfsize;
+
+ if (mc == NULL)
+ return EINVAL;
+
+ /* Set the defaults for no CTF present. That's not a crime! */
+ memset(mc, 0, sizeof(*mc));
+
+ /* cached mc? */
+ if (mod->mod_ctf != NULL) {
+ cmc = mod->mod_ctf;
+ *mc = *cmc;
+ return (0);
+ }
+
+ st = ksyms_get_mod(mod->mod_info->mi_name);
+
+ if (st != NULL) {
+ mc->nmap = st->sd_nmap;
+ mc->nmapsize = st->sd_nmapsize;
+ }
+
+ if (mod->mod_kobj == NULL) {
+ /* no kobj entry, try building from ksyms list */
+ if (st == NULL) {
+ return ENOENT;
+ }
+
+ ctfaddr = st->sd_ctfstart;
+ ctfsize = st->sd_ctfsize;
+
+ mc->symtab = st->sd_symstart;
+ mc->strtab = st->sd_strstart;
+ mc->strcnt = 0; /* XXX TBD */
+ mc->nsym = st->sd_symsize / sizeof(Elf_Sym);
+ } else {
+ if (kobj_find_section(mod->mod_kobj, ".SUNW_ctf", (void **)&ctfaddr, &ctfsize))
+ return ENOENT;
+
+ mc->symtab = mod->mod_kobj->ko_symtab;
+ mc->strtab = mod->mod_kobj->ko_strtab;
+ mc->strcnt = 0; /* XXX TBD */
+ mc->nsym = mod->mod_kobj->ko_symcnt;
+ }
+
+ if (ctfaddr == NULL) {
+ goto out;
+ }
+
+ /* Check the CTF magic number. (XXX check for big endian!) */
+ if (ctfaddr[0] != 0xf1 || ctfaddr[1] != 0xcf) {
+ goto out;
+ }
+
+ /* Check if version 2. */
+ if (ctfaddr[2] != 2)
+ goto out;
+
+ /* Check if the data is compressed. */
+ if ((ctfaddr[3] & 0x1) != 0) {
+ uint32_t *u32 = (uint32_t *) ctfaddr;
+
+ /*
+ * The last two fields in the CTF header are the offset
+ * from the end of the header to the start of the string
+ * data and the length of that string data. se this
+ * information to determine the decompressed CTF data
+ * buffer required.
+ */
+ sz = u32[CTF_HDR_STRTAB_U32] + u32[CTF_HDR_STRLEN_U32] +
+ CTF_HDR_SIZE;
+
+ compressed = 1;
+ } else {
+ /*
+ * The CTF data is not compressed, so the ELF section
+ * size is the same as the buffer size required.
+ */
+ sz = ctfsize;
+ }
+
+ /*
+ * Allocate memory to buffer the CTF data in it's decompressed
+ * form.
+ */
+ if (compressed) {
+ if ((ctfbuf = malloc(sz, M_TEMP, M_WAITOK)) == NULL) {
+ error = ENOMEM;
+ goto out;
+ }
+ ctftab = ctfbuf;
+ mc->ctfalloc = 1;
+ } else {
+ ctftab = (void *)ctfaddr;
+ }
+
+ /* Check if decompression is required. */
+ if (compressed) {
+ z_stream zs;
+ int ret;
+
+ /*
+ * The header isn't compressed, so copy that into the
+ * CTF buffer first.
+ */
+ memcpy(ctftab, ctfaddr, CTF_HDR_SIZE);
+
+ /* Initialise the zlib structure. */
+ memset(&zs, 0, sizeof(zs));
+ zs.zalloc = z_alloc;
+ zs.zfree = z_free;
+
+ if (inflateInit2(&zs, MAX_WBITS) != Z_OK) {
+ error = EIO;
+ goto out;
+ }
+
+ zs.avail_in = ctfsize - CTF_HDR_SIZE;
+ zs.next_in = ((uint8_t *) ctfaddr) + CTF_HDR_SIZE;
+ zs.avail_out = sz - CTF_HDR_SIZE;
+ zs.next_out = ((uint8_t *) ctftab) + CTF_HDR_SIZE;
+ inflateReset(&zs);
+ if ((ret = inflate(&zs, Z_FINISH)) != Z_STREAM_END) {
+ printf("%s(%d): zlib inflate returned %d\n", __func__, __LINE__, ret);
+ error = EIO;
+ goto out;
+ }
+ }
+
+ /* Got the CTF data! */
+ mc->ctftab = ctftab;
+ mc->ctfcnt = ctfsize;
+
+ /* cache it */
+ cmc = kmem_alloc(sizeof(mod_ctf_t), KM_SLEEP);
+
+ *cmc = *mc;
+ mod->mod_ctf = cmc;
+
+ /* We'll retain the memory allocated for the CTF data. */
+ ctfbuf = NULL;
+
+out:
+ if (ctfbuf != NULL)
+ free(ctfbuf, M_TEMP);
+
+ return (error);
+}
diff -r 1cae04d0440a -r 2da15793b3a9 sys/kern/kern_ksyms.c
--- a/sys/kern/kern_ksyms.c Fri Mar 12 21:37:37 2010 +0000
+++ b/sys/kern/kern_ksyms.c Fri Mar 12 21:43:10 2010 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: kern_ksyms.c,v 1.55 2010/03/01 22:27:07 darran Exp $ */
+/* $NetBSD: kern_ksyms.c,v 1.56 2010/03/12 21:43:11 darran Exp $ */
/*-
* Copyright (c) 2008 The NetBSD Foundation, Inc.
@@ -71,11 +71,12 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_ksyms.c,v 1.55 2010/03/01 22:27:07 darran Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_ksyms.c,v 1.56 2010/03/12 21:43:11 darran Exp $");
#if defined(_KERNEL) && defined(_KERNEL_OPT)
#include "opt_ddb.h"
#include "opt_ddbparam.h" /* for SYMTAB_SPACE */
+#include "opt_dtrace.h"
#endif
#define _KSYMS_PRIVATE
@@ -98,6 +99,13 @@
#include "ksyms.h"
+#define KSYMS_MAX_ID 65536
+#ifdef KDTRACE_HOOKS
+static uint32_t ksyms_nmap[KSYMS_MAX_ID]; /* sorted symbol table map */
+#else
+static uint32_t *ksyms_nmap = NULL;
+#endif
+
static int ksyms_maxlen;
static bool ksyms_isopen;
static bool ksyms_initted;
@@ -124,6 +132,7 @@
int ksyms_symsz;
int ksyms_strsz;
+int ksyms_ctfsz;
TAILQ_HEAD(, ksyms_symtab) ksyms_symtabs =
TAILQ_HEAD_INITIALIZER(ksyms_symtabs);
static struct ksyms_symtab kernel_symtab;
@@ -264,11 +273,21 @@
static void
addsymtab(const char *name, void *symstart, size_t symsize,
void *strstart, size_t strsize, struct ksyms_symtab *tab,
- void *newstart)
Home |
Main Index |
Thread Index |
Old Index