Module pmodule

pmodules allow users to augment snapshot data with custom analysis, annotations, pretty-printed data, etc. Below is a short reference example; see the pmodule tutorial for more details. The rest of this page contains documentation for the full Lua pmodule API.

Example:

local function postattach_cb(bt)
    local m = pmodule.match()
    m:set_fault()

    -- Example iterators.
    for thr in bt, m do
        for fr in thr do
            for var in fr do
                if var:type() == pmodule.variable_type.reference then
                    local addr = var:value()

                    var:annotate(pmodule.annotation.critical,
                        "[%x] %s - example annotation",
                        var:value(), var:name())
                end
            end
        end
    end

    -- Example global variable iteration.
    pmodule.log(pmodule.log_level.warning, "Global variables:");
    for var, object, cu in bt:variables(), {object = "crash", cu = "invalid_write.c"} do
        pmodule.log(pmodule.log_level.warning,
            "name: %s, value: %s, object: %s, cu: %s",
            var:name(), tostring(var:value()), object, cu)
    end

    -- Example TLS variable iteration.
    for thr in bt do
        pmodule.log(pmodule.log_level.warning, "TLS variables:");

        for var, object, cu in thr:variables(), {cu = "hang"} do
            pmodule.log(pmodule.log_level.warning,
                "name: %s, value: %s, object: %s, \z
                cu: %s",
                var:name(), tostring(var:value()), object, cu)
        end
    end

    -- Example global variable lookup by name.
    for var in bt:variables(), {name = "global_version"} do
        local str = pmodule.address_read_string(var:value(), 256)

        pmodule.log(pmodule.log_level.warning,
            "[%x] string: %s", var:value(), str)
    end

    pmodule.log(pmodule.log_level.warning, "process state: %d",
        bt:process_state())

    bt:add_tag("lua_tag")
    bt:add_kv_int("lua_key1", 42)
    bt:add_kv_string("lua_key2", "lua_value")
    bt:add_classifier("lua")
end

local function frame_cb(fr)
    -- Two ways to access frame parameters:
    for v, i in fr:fprm() do
        v:annotate(pmodule.annotation.critical, "lua: fprm %d", i)
    end

    for i = 0, math.huge do
        local v = fr:fprm_at(i)

        if not v then
            break
        end

        v:annotate(pmodule.annotation.critical, "lua: fprm_at %d", i)
    end

    local signal = fr:siginfo()
    if signal then
        fr:backtrace():annotate(
            pmodule.annotation.json,
            '{"json": {"context": "Signal", \z
            "Reason": "%s", \z
            "Populated": "%s", \z
            "Address": "%x", \z
            "Num": "%d", \z
            "Code": "%d", \z
            "String": "%s"}}',
            signal:reason(),
            tostring(signal:address_populated()),
            signal:address(),
            signal:num(),
            signal:code(),
            tostring(signal))
    end
end

local function pm_load()
    pmodule.register(pmodule.event.postattach, postattach_cb)

    local m = pmodule.match()

    m:add_object("crash")
    m:add_file("crash.c")
    m:add_frame_symbol("recurse", pmodule.match_type.substr)
    m:add_variable_base_type("crash_", pmodule.match_type.substr)
    m:add_variable_ptrace_type(pmodule.variable_type.tuple)

    pmodule.register(pmodule.event.variable,
        function(var)
            var:annotate(pmodule.annotation.critical, "lua: struct var")
        end, m)

    m:reset()
    pmodule.register(pmodule.event.frame, frame_cb, m)

    pmodule.log(pmodule.log_level.warning, "%s",
        pmodule.config_option("lua_option"))
end

pmodule.define{
    id = "pmodule_lua",
    load=pm_load,
    reset=function () pmodule.log(pmodule.log_level.warning, "pm_reset") end,
    unload=function () pmodule.log(pmodule.log_level.warning, "pm_unload") end

Brief content:

Functions:

pmodule.define{module_description}

pmodule.event_register(event_type, function[, match])

pmodule.log(log_level, fmt_string, ...)

pmodule.address_symbol(addr)

pmodule.symbol_address(symbol[, object])

pmodule.symbol_read_raw(symbol, object, size)

pmodule.address_read_raw(addr, size)

pmodule.symbol_read_string(symbol, object, size)

pmodule.address_read_string(addr, size)

pmodule.match()

pmodule.pmap_enabled()

pmodule.pmap_cached()

pmodule.backtrace()

pmodule.config_option(key)

pmodule.create_variable(type, name, addr, offset[, owner])

pmodule.create_frame()

pmodule.bt_query(symbol, object, cu)

pmodule.variable_from_bt(btvar)

pmodule.deref(bt_var[, address])

pmodule.sizeof(bt_var)

Methods:

backtrace:pid()

backtrace:pmap_entry(addr)

backtrace:application_name()

backtrace:process_state()

backtrace:add_tag(tag_name)

backtrace:add_kv_int(key, value)

backtrace:add_kv_string(key, value)

backtrace:add_classifier(classifier_name)

backtrace:annotate(level, fmt, ...)

backtrace

backtrace:variables()

thread:fault()

thread:tid()

thread:backtrace()

thread:n_frames()

thread:n_kframes()

thread:set_name(name)

thread:add_frame(frame[, first])

thread:annotate(level, fmt, ...)

thread

thread:variables()

frame:instruction()

frame:path()

frame:symbol()

frame:line_resolved()

frame:object_file()

frame:backtrace()

frame:thread()

frame:line()

frame:decl_line()

frame:siginfo()

frame:fprm_at(index)

frame:fprm()

frame:set_basename(basename)

frame:set_symbol(symbol)

frame:set_directory(directory)

frame:set_path(path)

frame:set_line(line)

frame:set_decl_line(line)

frame:add_variable(variable[, insert_after])

frame:add_frame(frame[, insert_after])

frame:annotate(level, fmt, vars)

frame

variable:address()

variable:symbol()

variable:type()

variable:type_name()

variable:base_type()

variable:name()

variable:owner()

variable:frame()

variable:thread()

variable:backtrace()

variable:fprm_offset()

variable:resolved()

variable:is_string()

variable:value()

variable:set_struct()

variable:set_array()

variable:set_function([symbol])

variable:set_string([symbol])

variable:set_string(value[, symbol])

variable:set_ref(value[, symbol])

variable:set_cdbl(real, imag)

variable:set_dbl(value)

variable:set_ull(value)

variable:set_ll(value)

variable:annotate(level, fmt, ...)

bt_variable:index()

match:reset()

match:add_object(object[, string_match])

match:add_file(filename[, string_match])

match:add_frame_symbol(symbol[, string_match])

match:add_base_type(base_type[, string_match])

match:add_variable_ptrace_type(type)

match:add_variable_name(name[, string_match])

match:set_fault([thread])

pmap:guard()

pmap:permissions(flag[, flag2, flag3, ...])

siginfo:reason()

siginfo:address_populated()

siginfo:address()

siginfo:num()

siginfo:code()

siginfo:tostring()

Functions

The module pmodule defines the following functions.

Function pmodule.define{module_description}

Defines a pmodule. This must be called when the Lua module is loaded (i.e. it should be a global call). The following are valid fields:

Parameters:

Returns:

nothing

Example:

pmodule.define{
    id = "pmodule_lua",
    load=pm_load,
    reset=function () pmodule.log(pmodule.log_level.warning, "pm_reset") end,
    unload=function () pmodule.log(pmodule.log_level.warning, "pm_unload") end

Back to module description.

Function pmodule.event_register(event_type, function[, match])

Registers an event callback. These functions are executed at specific points during snapshot generation:

Events/Phases:

Events may optionally be filtered by match filters; see pmodule.match() . Each event callback will receive as its first argument the relevant object - variable callbacks will receive variable objects, frame callbacks will receive frame objects, thread callbacks will receive thread objects, and all attach callbacks (pre, attach, and post) will receive the backtrace object.

Parameters:

Returns:

nothing

Back to module description.

Function pmodule.log(log_level, fmt_string, ...)

Logs a message. Supported log levels:

Parameters:

Returns:

nothing

Back to module description.

Function pmodule.address_symbol(addr)

Returns the string symbol associated with the given address.

Parameters:

Returns:

Back to module description.

Function pmodule.symbol_address(symbol[, object])

Returns the address of the given symbol in the optional object.

Parameters:

Returns:

Back to module description.

Function pmodule.symbol_read_raw(symbol, object, size)

Returns raw binary data of up to the specified length associated with the given symbol in the optional object.

Parameters:

Returns:

Back to module description.

Function pmodule.address_read_raw(addr, size)

Returns raw binary data of up to the specified length associated with the given address.

Parameters:

Returns:

Back to module description.

Function pmodule.symbol_read_string(symbol, object, size)

Returns a string of up to the specified length associated with the given symbol in the optional object.

Parameters:

Returns:

Back to module description.

Function pmodule.address_read_string(addr, size)

Returns a string of up to the specified length associated with the given address.

Parameters:

Returns:

Back to module description.

Function pmodule.match()

Creates a new match filter to be used during event registration and object iteration.

Parameters:

nothing

Returns:

Back to module description.

Function pmodule.pmap_enabled()

Parameters:

nothing

Returns:

Back to module description.

Function pmodule.pmap_cached()

Parameters:

nothing

Returns:

Back to module description.

Function pmodule.backtrace()

Retrieves the backtrace object associated with the snapshot. Valid only during event callbacks.

Parameters:

nothing

Returns:

Back to module description.

Function pmodule.config_option(key)

Returns the value associated with the given key through a ptrace CLI option.

Parameters:

nothing

Returns:

Back to module description.

Function pmodule.create_variable(type, name, addr, offset[, owner])

Synthesizes a variable. These should eventually be added to the backtrace via frame:add_variable(var) . The variable's value and type should be set through one of the variable:set_* methods.

Parameters:

Returns:

Back to module description.

Function pmodule.create_frame()

Synthesizes a frame to which a user can add variables. Synthesized frames should eventually be added to the backtrace via thread:add_frame(fr) and frame:add_frame(fr) .

Parameters:

nothing

Returns:

Back to module description.

Function pmodule.bt_query(symbol, object, cu)

Queries for a global variable. The returned bt_variable may be used with the standard bt_variable interface (see bt_variable:index()).

Parameters:

Returns:

Back to module description.

Function pmodule.variable_from_bt(btvar)

Synthesizes a pmodule_variable from a bt_variable. This will allow querying for specific variable data (e.g. value, address, name) via the pmodule variable API. bt_variables allow querying for only struct members (see bt_variable:index()). Variables synthesized this way will be finalized/freed. They cannot be added to the snapshot. All synthesized variables (to be added to the snapshot)must go through the synthesis API.

Parameters:

Returns:

Back to module description.

Function pmodule.deref(bt_var[, address])

Dereferences a reference bt_variable either at the optionally given address or at the value of the given bt_variable.

Parameters:

Returns:

Back to module description.

Function pmodule.sizeof(bt_var)

Parameters:

Returns:

Back to module description.

Methods

The module pmodule defines the following methods.

Method backtrace:pid()

Parameters:

nothing

Returns:

Back to module description.

Method backtrace:pmap_entry(addr)

Parameters:

Returns:

Back to module description.

Method backtrace:application_name()

Parameters:

nothing

Returns:

Back to module description.

Method backtrace:process_state()

Possible process states:

Parameters:

nothing

Returns:

Back to module description.

Method backtrace:add_tag(tag_name)

Parameters:

Returns:

nothing

Back to module description.

Method backtrace:add_kv_int(key, value)

Parameters:

Returns:

nothing

Back to module description.

Method backtrace:add_kv_string(key, value)

Parameters:

Returns:

nothing

Back to module description.

Method backtrace:add_classifier(classifier_name)

Parameters:

Returns:

nothing

Back to module description.

Method backtrace:annotate(level, fmt, ...)

Annotates a variable with a message. The supported annotation levels are:

Variables, frames, threads, and the overarching backtrace object may be annotated with additional data. All annotation types but PAT_JSON will appear as text attached to the specified object; PAT_JSON will result in the specified text being parsed as a json object to be attached to the specified object.

JSON annotations must be complete, valid JSON objects. Invalid JSON will be discarded.

JSON annotation formatting:

Hydra will parse structured JSON annotations as follows:


    "json": {
        "context" : "Title",
        "key1": "value",
        "key2": "value",
        "key3": {
            "key1": "value",
            "key2": "value"
        }
        ...
    }

Rendered output (in Hydra):

- Title
     key1   value
     key2   value
   - key3
        key1    value
        key2    value

"json" must be the overall key to the annotation object, as the annotation will be embedded into another json object.

"context" is the title of this particular section; the rest of the output will appear in a hierarchy under the "context" title.

All other fields are key value pairs. Any values which are objects themselves will increase the hierarchy level by one until that object ends. Thus, output may be structured into a tree view.

Parameters:

Returns:

nothing

Back to module description.

Method backtrace

When used as a function, this returns a thread iterator compatible with generic for. If a match filter is desired, it should be the second expression (invariant state) of the generic for.

Parameters:

Returns:

Example:

local m = pmodule.match()
local bt = pmodule.backtrace()
for thr in bt[, m] do
    -- some action
end

Back to module description.

Method backtrace:variables()

This returns a global variable iterator compatible with generic for. If a filter is desired, the user may specify a table as the invariant state (2nd expression of the generic for). All the following fields are optional:

Parameters:

Returns:

Example:

for var, object, cu in bt:variables(), {object = "crash", cu = "invalid_write.c"} do
    -- actions
end

Back to module description.

Method thread:fault()

Parameters:

nothing

Returns:

Back to module description.

Method thread:tid()

Parameters:

nothing

Returns:

Back to module description.

Method thread:backtrace()

Parameters:

nothing

Returns:

Back to module description.

Method thread:n_frames()

Parameters:

nothing

Returns:

Back to module description.

Method thread:n_kframes()

Parameters:

nothing

Returns:

Back to module description.

Method thread:set_name(name)

Parameters:

Returns:

nothing

Back to module description.

Method thread:add_frame(frame[, first])

Parameters:

Returns:

nothing

Back to module description.

Method thread:annotate(level, fmt, ...)

Annotates a thread with a message. See backtrace:annotate(level, fmt, ...) for more details regarding this API.

Parameters:

Returns:

nothing

Back to module description.

Method thread

When used as a function, this returns a frame iterator compatible with generic for. If a match filter is desired, it should be the second expression (invariant state) of the generic for.

Parameters:

Returns:

Example:

local m = pmodule.match()
local thr = ...
for fr in thr[, m] do
    -- some action
end

Back to module description.

Method thread:variables()

This returns a TLS variable iterator compatible with generic for. If a filter is desired, the user may specify a table as the invariant state (2nd expression of the generic for). All the following fields are optional:

Parameters:

Returns:

Example:

for var, object in thr:variables(), {cu = "hang"} do
    -- actions
end

Back to module description.

Method frame:instruction()

Parameters:

nothing

Returns:

Back to module description.

Method frame:path()

Parameters:

nothing

Returns:

Back to module description.

Method frame:symbol()

Parameters:

nothing

Returns:

Back to module description.

Method frame:line_resolved()

Parameters:

nothing

Returns:

Back to module description.

Method frame:object_file()

Parameters:

nothing

Returns:

Back to module description.

Method frame:backtrace()

Parameters:

nothing

Returns:

Back to module description.

Method frame:thread()

Parameters:

nothing

Returns:

Back to module description.

Method frame:line()

Parameters:

nothing

Returns:

Back to module description.

Method frame:decl_line()

Parameters:

nothing

Returns:

Back to module description.

Method frame:siginfo()

See the siginfo methods for usage.

Parameters:

nothing

Returns:

Back to module description.

Method frame:fprm_at(index)

Parameters:

Returns:

Back to module description.

Method frame:fprm()

Per iteration, the user will receive {pmodule.variable} variable, {integer} fprm_index .

Parameters:

nothing

Returns:

Back to module description.

Method frame:set_basename(basename)

Parameters:

Returns:

nothing

Back to module description.

Method frame:set_symbol(symbol)

Parameters:

Returns:

nothing

Back to module description.

Method frame:set_directory(directory)

Parameters:

Returns:

nothing

Back to module description.

Method frame:set_path(path)

Parameters:

Returns:

nothing

Back to module description.

Method frame:set_line(line)

Parameters:

Returns:

nothing

Back to module description.

Method frame:set_decl_line(line)

Parameters:

Returns:

nothing

Back to module description.

Method frame:add_variable(variable[, insert_after])

Parameters:

Returns:

nothing

Back to module description.

Method frame:add_frame(frame[, insert_after])

Parameters:

Returns:

nothing

Back to module description.

Method frame:annotate(level, fmt, vars)

Annotates a frame with a message. See backtrace:annotate(level, fmt, ...) for more details regarding this API.

Parameters:

Returns:

nothing

Back to module description.

Method frame

When used as a function, this returns a variable iterator compatible with generic for. If a match filter is desired, it should be the second expression (invariant state) of the generic for.

Parameters:

Returns:

Example:

local m = pmodule.match()
local fr = ...
for var in fr[, m] do
    -- some action
end

Back to module description.

Method variable:address()

Parameters:

nothing

Returns:

Back to module description.

Method variable:symbol()

Auxiliary symbol data associated with the variable, depending on its type and availability.

Parameters:

nothing

Returns:

Back to module description.

Method variable:type()

Possible variable types:

Parameters:

nothing

Returns:

Back to module description.

Method variable:type_name()

Parameters:

nothing

Returns:

Back to module description.

Method variable:base_type()

Parameters:

nothing

Returns:

Back to module description.

Method variable:name()

Parameters:

nothing

Returns:

Back to module description.

Method variable:owner()

Parameters:

nothing

Returns:

Back to module description.

Method variable:frame()

Parameters:

nothing

Returns:

Back to module description.

Method variable:thread()

Parameters:

nothing

Returns:

Back to module description.

Method variable:backtrace()

Parameters:

nothing

Returns:

Back to module description.

Method variable:fprm_offset()

Parameters:

nothing

Returns:

Back to module description.

Method variable:resolved()

Parameters:

nothing

Returns:

Back to module description.

Method variable:is_string()

Parameters:

nothing

Returns:

Back to module description.

Method variable:value()

The value(s) returned depends on the variable's type, as follows:

Parameters:

nothing

Returns:

Back to module description.

Method variable:set_struct()

Parameters:

nothing

Returns:

nothing

Back to module description.

Method variable:set_array()

Parameters:

nothing

Returns:

nothing

Back to module description.

Method variable:set_function([symbol])

Parameters:

Returns:

nothing

Back to module description.

Method variable:set_string([symbol])

Parameters:

Returns:

nothing

Back to module description.

Method variable:set_string(value[, symbol])

Parameters:

Returns:

nothing

Back to module description.

Method variable:set_ref(value[, symbol])

Parameters:

Returns:

nothing

Back to module description.

Method variable:set_cdbl(real, imag)

Parameters:

Returns:

nothing

Back to module description.

Method variable:set_dbl(value)

Parameters:

Returns:

nothing

Back to module description.

Method variable:set_ull(value)

Parameters:

Returns:

nothing

Back to module description.

Method variable:set_ll(value)

Parameters:

Returns:

nothing

Back to module description.

Method variable:annotate(level, fmt, ...)

Annotates a variable with a message. See backtrace:annotate(level, fmt, ...) for more details regarding this API.

Parameters:

Returns:

nothing

Back to module description.

Method bt_variable:index()

bt_variables may be used to access member fields in structures with a familiar syntax -- i.e., variable_name.member_field. Member access works only on variables of struct type, with one exception: references to structs are automatically dereferenced (by as many levels necessary to get to the underlying struct type) before the member field is queried. Once the desired bt_variable is retrieved, it may be synthesized into a pmodule variable (see pmodule.variable_from_bt(btvar)) for use with the standard pmodule variable API to extract the various data fields (e.g. address, value, symbol).

Parameters:

nothing

Returns:

Back to module description.

Method match:reset()

Resets the match object to its base (empty) state.

Parameters:

nothing

Returns:

nothing

Back to module description.

Method match:add_object(object[, string_match])

Acceptable values for string_match:

Parameters:

Returns:

nothing

Back to module description.

Method match:add_file(filename[, string_match])

Acceptable values for string_match:

Parameters:

Returns:

nothing

Back to module description.

Method match:add_frame_symbol(symbol[, string_match])

Acceptable values for string_match:

Parameters:

Returns:

nothing

Back to module description.

Method match:add_base_type(base_type[, string_match])

Acceptable values for string_match:

Parameters:

Returns:

nothing

Back to module description.

Method match:add_variable_ptrace_type(type)

Parameters:

Returns:

nothing

Back to module description.

Method match:add_variable_name(name[, string_match])

Acceptable values for string_match:

Parameters:

Returns:

nothing

Back to module description.

Method match:set_fault([thread])

Fault matches iff:

Parameters:

Returns:

nothing

Back to module description.

Method pmap:guard()

Parameters:

nothing

Returns:

Back to module description.

Method pmap:permissions(flag[, flag2, flag3, ...])

Flag can be any of the following values:

Parameters:

Returns:

Back to module description.

Method siginfo:reason()

Parameters:

nothing

Returns:

Back to module description.

Method siginfo:address_populated()

Parameters:

nothing

Returns:

Back to module description.

Method siginfo:address()

Parameters:

nothing

Returns:

Back to module description.

Method siginfo:num()

Parameters:

nothing

Returns:

Back to module description.

Method siginfo:code()

Parameters:

nothing

Returns:

Back to module description.

Method siginfo:tostring()

This is invoked by calling tostring() on a siginfo object.

Parameters:

nothing

Returns:

Back to module description.

Back to top.