System and application tracing can happen in the kernel. It has to
be configured and enabled through the
ioctl(2)
interface exposed by the pseudo-device /dev/dt.
This device can only be opened when the
kern.allowdt
sysctl(2)
variable is set.
The ioctl(2) command codes below are defined in
<dev/dt/dtvar.h>.
DTIOCGPLIST
struct dtioc_probe *dtpr
- Get available probe entries.
struct dtioc_probe {
size_t dtpr_size;
struct dtioc_probe_info *dtpr_probes;
};
If dtpr_size is non-zero, as many probes
as possible that can fit into this size will be copied into the supplied
buffer. On exit, dtpr_size is always set to the
total size required to hold all probe entries (i.e., it is set to
sizeof(struct dtioc_probe_info) *
dt_nprobes).
DTIOCGSTATS
struct dtioc_stat *dtst
- Get statistics for current recording.
struct dtioc_stat {
uint64_t dtst_readevt;
uint64_t dtst_dropevt;
};
DTIOCRECORD
int on
- Start or stop recording.
DTIOCPRBENABLE
struct dtioc_req *dtrq
- Enable the given probe for recording.
struct dtioc_req {
uint32_t dtrq_pbn;
struct dt_filter dtrq_filter;
uint32_t dtrq_rate;
uint64_t dtrq_evtflags;
};
DTIOCRDVNODE
struct *dtioc_rdvn
- Resolve the instruction pointer from the traced process to the ELF object.
struct dtioc_rdvn {
pid_t dtrv_pid;
int dtrv_fd;
caddr_t dtrv_va;
caddr_t dtrv_offset;
caddr_t dtrv_start;
size_t dtrv_len;
};
The caller populates dtrv_pid with the
process ID of the traced process and dtrv_va with
the program counter address to look up.
On success, the remaining members are populated.
dtrv_fd is the file descriptor to the DSO file
that dtrv_va belongs to.
dtrv_len is the length of the DSO file.
dtrv_offset and dtrv_start
are the relative offset of dtrv_va to the start of
the text segment and the base address of that segment respectively.
To calculate the relative offset of
dtrv_va in the DSO the following calculation can
be used:
iOffset = dtrv_va - dtrv_start +
dtrv_offset
The segment can be found by walking the ELF program headers
and looking for the mapping where iOffset is included in the range
[GElf_Phdr.p_offset, GElf_Phdr.p_offset + GElf_Phdr.p_filesz)
Using the GElf_Phdr.p_vaddr the base
address of the segment can be calculated by
lbase = dtrv_start -
GElf_Phdr.p_vaddr
For symbol lookups the offset can now be calculated as
symOffset = dtrv_va -
lbase
- /dev/dt
- dynamic tracing device.
An open of /dev/dt will fail if:
- [
EPERM]
- the kern.allowdt
sysctl(2) variable wasn't set.
- [
ENOMEM]
- not enough memory space was available.
The dt dynamic tracing mechanism first
appeared in OpenBSD 6.7.