Skip to content

Commit 8e99c7d

Browse files
committed
Add support for SDT probes.
1 parent 2da32cb commit 8e99c7d

File tree

17 files changed

+397
-49
lines changed

17 files changed

+397
-49
lines changed

Changes

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,18 @@
1+
Sat Oct 19 17:47:23 2013 fox
2+
3+
844* driver/dtrace_linux.c: Fix for /proc/dtrace/trace on 3.11 kernel
4+
which doesnt like big blobs of output.
5+
6+
Fri Oct 18 22:51:33 2013 fox
7+
8+
843* driver/systrace.c: Dont GPF on an amd64 kernel with no
9+
32-bit syscalls support when catting /proc/dtrace/syscall.
10+
11+
Thu Oct 17 23:20:00 2013 fox
12+
13+
842* sdt_linux.c, prov_common.c, dtrace_linux.c: Support for
14+
dynamic/private SDT probes in loadable modules.
15+
116
Sat Oct 12 08:07:40 2013 fox
217

318
841* intr.c: Fix for 3.11 kernel (store_gdt)

Packages

Lines changed: 0 additions & 25 deletions
This file was deleted.

README

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Linux port of DTrace
22

3-
Aug 2013
3+
Oct 2013
44
Paul D. Fox
55
66
http://www.twitter.com/crispeditor
@@ -162,6 +162,16 @@ make unl
162162
make test
163163
To run the userland cmd/dtrace regression test
164164

165-
For AS4/Centos
166-
==============
167-
yum install elfutils-libelf-devel
165+
Dependencies
166+
============
167+
To build dtrace for linux requires a number of tools - mostly
168+
the basic Unix development tools, plus you will need the kernel
169+
source/build tree. dtrace does not affect or touch your kernel
170+
sources, but it needs the normal header files for creating a
171+
loadable module.
172+
173+
Examine the following scripts to help identify missing packages:
174+
175+
tools/get-deps-arch.sh
176+
tools/get-deps-fedora.sh
177+
tools/get-deps.pl

Status.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ Working Features
3535
o ARMv6/RaspberryPi on 3.4.6 kernel (USDT is not tested or likely to work)
3636
- the instr provider isnt supported (yet)
3737
- no SMP support
38+
o driver-2/hworld.c - example SDT loadable driver, demonstrating dynamic
39+
SDT probes. See doc/sdt-probes.txt for more details.
3840

3941
Partially Working / Not yet quality controlled:
4042

archive.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
NAME=dtrace
22
MAJ_VERSION=1
3-
MIN_VERSION=0149
3+
MIN_VERSION=0150
44
EXCLUDE="*.ko *.o .git"
55
EXCLUDE_DIRS="build-"
6-
#date Sat Jul 13 17:15:26 BST 2013
6+
#date Sat Oct 12 09:35:02 BST 2013

cmd/ctfconvert/makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ all:
5454
@. ../../build/port.sh ; \
5555
if [ ! -f /usr/lib/libdwarf.a -a ! -f /usr/lib64/libdwarf.a ]; then \
5656
echo "=================================================================" ; \
57-
echo "=== You need /usr/lib/libdwarf.a or /ur/lib64/libdwarf.a " ; \
57+
echo "=== You need /usr/lib/libdwarf.a or /usr/lib64/libdwarf.a " ; \
5858
echo "=== (libdw is not yet supported) to build." ; \
5959
echo "=== " ; \
6060
echo "=== apt-get install binutils-dev" ; \

doc/sdt-probes.txt

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
SDT Probes
2+
Date: 20 Oct 2013
3+
4+
SDT probes on Solaris are probes which are actual calls to DTrace,
5+
compiled when the kernel or module is compiled. Calls to variations
6+
of the DTRACE_PROBE macros insert appropriate markers so
7+
that these probe points are exposed and can be seen in "dtrace -l".
8+
9+
DTrace for Linux assumes we are not going to change the kernel.
10+
Changes to the boot-loaded kernel require code to parse out these
11+
probes and make them a part of DTrace. This is not presently implemented.
12+
13+
However DTrace does provide for SDT probes in dynamically loaded
14+
modules. The code in driver-2 provides a simple hello-world
15+
driver which exposes /proc/hello-world. The open() and read()
16+
code shows the use of SDT probes.
17+
18+
The probes work by calling a dummy function - the dummy function
19+
is a dtrace mangled name encoding the provider/probename/function,
20+
and as the driver is loaded, you can see the probes in "dtrace -l"
21+
and use them as any other probe.
22+
23+
If the driver is unloaded, the probes are removed, as expected, allowing
24+
debugging of a driver and reloading without causing harm.
25+
26+
These probes are invoked as :
27+
28+
<pre>
29+
DTRACE_SDT_PROBE1(hworld, open_module, open1, entry, num_opens);
30+
</pre>
31+
32+
The first four arguments correspond to the provider,
33+
module, probename, and function name. These are mostly arbitrary,
34+
although the module name is *ignored*. The actual driver module
35+
name is inserted at this point, to ensure the corresponding driver
36+
unload does the right thing.
37+
38+
The remaining arguments are available as probe arguments. Presently,
39+
they are typeless (integer), so you would need to cast them to an
40+
appropriate type if you want to access internal structures.

driver/dtrace_linux.c

Lines changed: 89 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1169,6 +1169,28 @@ static int count;
11691169
}
11701170
return NULL;
11711171
}
1172+
/**********************************************************************/
1173+
/* Convert an address to a function name (if possible). */
1174+
/**********************************************************************/
1175+
int
1176+
get_proc_name(unsigned long addr, char *buf)
1177+
{
1178+
unsigned long symsize = 0;
1179+
unsigned long offset;
1180+
char *modname = NULL;
1181+
static const char *(*my_kallsyms_lookup)(unsigned long addr,
1182+
unsigned long *symbolsize,
1183+
unsigned long *offset,
1184+
char **modname, char *namebuf);
1185+
1186+
*buf = '\0';
1187+
if (my_kallsyms_lookup == NULL)
1188+
my_kallsyms_lookup = get_proc_addr("kallsyms_lookup");
1189+
if (my_kallsyms_lookup == NULL)
1190+
return 0;
1191+
my_kallsyms_lookup(addr, &symsize, &offset, &modname, buf);
1192+
return symsize;
1193+
}
11721194
int
11731195
sulword(const void *addr, ulong_t value)
11741196
{
@@ -2861,12 +2883,6 @@ static struct file_operations proc_dtrace_stats = {
28612883
.release = single_release
28622884
};
28632885

2864-
/** "proc/dtrace/trace" */
2865-
static int proc_dtrace_trace_show(struct seq_file *seq, void *v)
2866-
{
2867-
// TODO: or we can use dtracedrv_read() instead
2868-
return seq_printf(seq, "%s\n", dtrace_buf);
2869-
}
28702886
/**********************************************************************/
28712887
/* Special hack for debugging. */
28722888
/**********************************************************************/
@@ -2881,9 +2897,74 @@ static ssize_t proc_dtrace_trace_write_proc(struct file *fp, const char __user *
28812897
return count;
28822898
}
28832899

2900+
/**********************************************************************/
2901+
/* Code for /proc/dtrace/trace */
2902+
/**********************************************************************/
2903+
2904+
static void *proc_dtrace_trace_seq_start(struct seq_file *seq, loff_t *pos)
2905+
{
2906+
if (*pos < log_bufsiz)
2907+
return pos;
2908+
return NULL;
2909+
}
2910+
static void *proc_dtrace_trace_seq_next(struct seq_file *seq, void *v, loff_t *pos)
2911+
{
2912+
(*pos)++;
2913+
if (*pos >= log_bufsiz / 1024)
2914+
return NULL;
2915+
2916+
return pos;
2917+
}
2918+
static void proc_dtrace_trace_seq_stop(struct seq_file *seq, void *v)
2919+
{
2920+
}
2921+
static int proc_dtrace_trace_seq_show(struct seq_file *seq, void *v)
2922+
{ char *cp;
2923+
extern int dbuf_i;
2924+
loff_t *pos = v;
2925+
int n = (int) (long) *pos;
2926+
int n1 = 0;
2927+
2928+
if (n >= log_bufsiz)
2929+
return 0;
2930+
2931+
/***********************************************/
2932+
/* Skip any nulls since we may not have */
2933+
/* filled the buffer yet. */
2934+
/***********************************************/
2935+
cp = dtrace_buf + dbuf_i;
2936+
for (n1 = 0; n1 < log_bufsiz && *cp == '\0'; n1++) {
2937+
if (++cp >= &dtrace_buf[log_bufsiz])
2938+
cp = dtrace_buf;
2939+
}
2940+
2941+
n = (cp - dtrace_buf + n * 1024) % log_bufsiz;
2942+
cp = dtrace_buf + n;
2943+
2944+
/***********************************************/
2945+
/* Now return the next block of text up */
2946+
/* until the circular index. */
2947+
/***********************************************/
2948+
for (n1 = 0; cp != &dtrace_buf[dbuf_i] && n1 < 1024; ) {
2949+
if (cp >= &dtrace_buf[log_bufsiz])
2950+
cp = dtrace_buf;
2951+
if (*cp && seq_write(seq, cp, 1))
2952+
break;
2953+
cp++;
2954+
//(*pos)++;
2955+
n1++;
2956+
}
2957+
return 0;
2958+
}
2959+
struct seq_operations proc_dtrace_trace_show_ops = {
2960+
.start = proc_dtrace_trace_seq_start,
2961+
.next = proc_dtrace_trace_seq_next,
2962+
.stop = proc_dtrace_trace_seq_stop,
2963+
.show = proc_dtrace_trace_seq_show,
2964+
};
28842965
static int proc_dtrace_trace_single_open(struct inode *inode, struct file *file)
28852966
{
2886-
return single_open(file, &proc_dtrace_trace_show, NULL);
2967+
return seq_open(file, &proc_dtrace_trace_show_ops);
28872968
}
28882969
static struct file_operations proc_dtrace_trace = {
28892970
.owner = THIS_MODULE,
@@ -2894,7 +2975,7 @@ static struct file_operations proc_dtrace_trace = {
28942975
.write = proc_dtrace_trace_write_proc
28952976
};
28962977

2897-
/** \proc */
2978+
/** /proc */
28982979

28992980
static int dtracedrv_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
29002981
{ int ret;

driver/dtrace_linux.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,7 @@ typedef struct pf_info_t {
368368
uint8_t *st_value;
369369
int (*func_entry)(struct pf_info_t *, uint8_t *, int, int);
370370
int (*func_return)(struct pf_info_t *, uint8_t *, int);
371+
int (*func_sdt)(struct pf_info_t *, uint8_t *, int, int);
371372
void *retptr;
372373
int flags;
373374
} pf_info_t;
@@ -421,6 +422,7 @@ timeout_id_t timeout(void (*func)(void *), void *arg, unsigned long ticks);
421422
void untimeout(timeout_id_t id);
422423
void *prcom_get_arg(int n, int size);
423424
void *par_setup_thread1(struct task_struct *tp);
425+
int get_proc_name(unsigned long, char *buf);
424426

425427
/**********************************************************************/
426428
/* Some kernels dont define if not SMP, but we define anyway so */

driver/fbt_linux.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -765,7 +765,9 @@ fbt_provide_function(struct modctl *mp, par_module_t *pmp,
765765
uint8_t *instr, uint8_t *limit, int symndx)
766766
{
767767
pf_info_t inf;
768+
int io_prov_sdt(pf_info_t *infp, uint8_t *instr, int size, int modrm);
768769

770+
memset(&inf, 0, sizeof inf);
769771
inf.mp = mp;
770772
inf.pmp = pmp;
771773
inf.modname = modname;
@@ -776,6 +778,7 @@ fbt_provide_function(struct modctl *mp, par_module_t *pmp,
776778

777779
inf.func_entry = fbt_prov_entry;
778780
inf.func_return = fbt_prov_return;
781+
inf.func_sdt = io_prov_sdt;
779782

780783
dtrace_parse_function(&inf, instr, limit);
781784
}

0 commit comments

Comments
 (0)