Wednesday, August 12, 2015

dtrace newbie HOWTO: listing providers AND structures

One of the first things that I wanted to learn about dtrace was the answer to the question: "How do I figure out where I can put hooks to trace system activities?"

This is accomplished with 'dtrace -l', which lists all the possible providers to which dtrace scripts can be attached.

Once you find a provider of interest, e.g. io:::start(), you can again use the list (-l) option to take a peek into the kind of data that is accessible to you:

# dtrace -lvn io:::start

   ID   PROVIDER            MODULE                          FUNCTION NAME
62099         io            kernel                                   start

    Probe Description Attributes
        Identifier Names: Private
        Data Semantics:   Private
        Dependency Class: Unknown

    Argument Attributes
        Identifier Names: Private
        Data Semantics:   Private
        Dependency Class: ISA

    Argument Types
        args[0]: struct bio *
        args[1]: struct devstat *


The next logical question is, "What is in struct bio? What is in struct devstat?"

You could find the answer by grepping through /usr/include/sys. However, there's a much faster way to find out what you can look at. This is the critical piece of information that I couldn't find in other HOWTO manuals on the Internet:

# dtrace -qn 'io:::start{print(*args[0]); exit(0); }'

struct bio {
    uint8_t bio_cmd = 0x2
    uint8_t bio_flags = 0
    uint8_t bio_cflags = 0
    uint8_t bio_pflags = 0
    struct cdev *bio_dev = 0
    struct disk *bio_disk = 0xfffff80012144000
    off_t bio_offset = 0x116948cb000
    long bio_bcount = 0x1000
    caddr_t bio_data = 0xfffffe0005ada000
    struct vm_page **bio_ma = 0
    int bio_ma_offset = 0
    int bio_ma_n = 0
    int bio_error = 0
    long bio_resid = 0
    void (*)() bio_done = kernel`g_disk_done
    void *bio_driver1 = 0
    void *bio_driver2 = 0
    void *bio_caller1 = 0
    void *bio_caller2 = 0
    struct bio_queue = {
        struct bio *tqe_next = 0
        struct bio **tqe_prev = 0
    }
    const char *bio_attribute = 0
    struct g_consumer *bio_from = 0
    struct g_provider *bio_to = 0
    off_t bio_length = 0x1000
    off_t bio_completed = 0
    u_int bio_children = 0
    u_int bio_inbed = 0
    struct bio *bio_parent = 0xfffff8018178f2e8
    struct bintime bio_t0 = {
        time_t sec = 0x24d28
        uint64_t frac = 0x4543b859cc1368f0
    }
    bio_task_t *bio_task = 0
    void *bio_task_arg = 0
    void *bio_classifier1 = 0
    void *bio_classifier2 = 0
    daddr_t bio_pblkno = 0x8b4a4658
}


Now, THAT was easy!

No comments: