Next: , Previous: , Up: Top   [Contents][Index]


2 API Reference

This chapter describes the public API of Libpatch. It’s found under single architecture independent header file <libpatch/patch.h>. The architecture dependent header is automatically included in this header. Thus, the following code snippet is sufficiant to use Libpatch:

#include <libpatch/patch.h>

However, you might have to do more depending on which language you’re using Libpatch from. For example if importing in a C++ file:

extern "C" {
#include <libpatch/patch.h>
}

2.1 Types

2.1.1 Enumerations

Enum: patch_err

Denote an error code. Almost all functions provided by Libpatch return this type. Like the integers, the enum can be divided into three classes. The value PATCH_OK is the neutral value and represent no error. Values that are inferior to it are always negative and denote bugs in the library. For example, if you ever get PATCH_BUG, the library can be considered to be in an inconsitent state and so is your program since the latter is transformed by the former. In this case, it’s recommended to save wathever state you can and report the bug. Finally, values that are superior to PATCH_OK are always positive and denote a none fatal error of the call just made or a result of a batched operation. See patch_commit for an understanding of batched operation.

Note that this enumeration is not useful on its own for understanding the errors that you have. It’s rather intended to be used for checking if every went right. To understand the errors see patch_error_string.

PATCH_BUG

There’s a bug in the library. Save any state that you can and report the bug.

PATCH_OK

Everything went fine.

PATCH_EINVAL

Invalid arguments passed to the function.

PATCH_ENOTSUP

Operation is not supported with this version of the library.

PATCH_EFINI

Error while finalization of the library.

PATCH_EFAIL

Fail to patch.

PATCH_ESYS

System error. Note that errno is of no used here.

PATCH_ECONF

Error while configuring the library.

PATCH_ENEXIST

Patch does not exist.

PATCH_EEXIST

Patch already exist.

PATCH_EDISASM

Disassembler error.

PATCH_EDWARF

Dwarf error.

PATCH_EINIT

Library is not initialiezd.

Enum: patch_opt_choice

These are options that can be configured to change how the library internally do things. Some options are only configurable at the initialization of the library. See patch_init. Other options can also be configured at runtime after the initialization. See patch_configure.

PATCH_OPT_HASHMAP_POW2_SIZE

Power of two for the size of hashmaps. This effectively change number of buckets in the hashmaps created by the library. This is intented to be used primalary during testing for better coverage. However, you can use to reduce the memory footprint by a small margin, while augmenting the runtime overhead.

PATCH_OPT_PANIC_HOOK

Install panic hook. When Libpatch encounters a fatal error, the internal function patch_panic is called. If no hook were installed, a backtrace is printed and _Exit is called. If however you have important states to save, you can install a hook to be called before. The hook can even jump out of the library – e.g. by using longjmp – and continue the program. However if you do so, note that the library is in an inconsitent state and no function of the library can be used for the rest of the program.

This option can be configured at runtime.

PATCH_OPT_SIGILL_BOOLEAN

Use SIGILL instead of SIGTRAP. Internally, Libpatch will use SIGTRAP – and SIGILL on some architecture – for slow paths. However, if you need to use SIGTRAP for you own usage – e.g. under GDB – then by enabling this option, Libpatch will only use SIGILL.

PATCH_OPT_DEBUG_PATH_STR

Where to find *.debug files (.gnu_debuglink). Internally, Libpatch uses libdwfl for resolving addresses and symbols. Thus, if your program has its debug symbols in another file, you need to specify the path – at any level – under which it can be found. This option can be used multiple time for providing multiple paths.

Enum: patch_op_type

Type of operation to be done on a queued operation. See patch_queue.

PATCH_OP_INSTALL

Install a patch.

PATCH_OP_UNINSTALL

Uninstall a patch.

2.1.2 Typedefs

Typedef: patch_probe

Function to execute when hitting a tracepoint.

The signature is void (*)(struct patch_probe_context *).

Typedef: patch_reg

Architecture dependent unsigned integer value for a register.

2.1.3 Constants

Constant: PATCH_ARCH_GREGS_COUNT

Number of general registers that are in the gregs field of a patch_probe_context struct.

2.1.3.1 x86-64

These constants are indexes that can be used for reading the value of general registers of the gregs field of a patch_probe_context struct on x86-64 systems.

Constant: PATCH_X86_64_RAX
Constant: PATCH_X86_64_RBX
Constant: PATCH_X86_64_RCX
Constant: PATCH_X86_64_RDX
Constant: PATCH_X86_64_RSI
Constant: PATCH_X86_64_RDI
Constant: PATCH_X86_64_RBP
Constant: PATCH_X86_64_R8
Constant: PATCH_X86_64_R9
Constant: PATCH_X86_64_R10
Constant: PATCH_X86_64_R11
Constant: PATCH_X86_64_R12
Constant: PATCH_X86_64_R13
Constant: PATCH_X86_64_R14
Constant: PATCH_X86_64_R15

2.1.4 Structures

Struct: patch_opt

Configurable option.

Options are selected by the what field. The value of the option is one of the member of the anonymous union. Typically, the type suffix of the option choice is the member you should use.

Example:

patch_opt opts[] = {
          {
             .what    = PATCH_OPT_SIGILL_BOOLEAN,
             .boolean = true
          },
          {
             .what = PATCH_OPT_PANIC_HOOK,
             .hook = my_hook
          },
          {
             .what = PATCH_OPT_DEBUG_PATH_STR,
             .str  = "/path/to/debug/symbols"
          }
};
Struct: patch_probe_context

Context passed to a probe.

.status

Status register.

.pc

Program counter register.

.sp

Stack pointer register.

.gregs

General purpose registers. Does not include the above registers.

.user_data

User data passed during installation of the tracepoint. See patch_queue.

Struct: patch_addr

Tracepoint’s location.

.func_sym

Symbol of function where the tracepoint is or NULL.

.insn_offset

Offset of instruction in function func_sym where the tracepoint is.

.patch_addr

Absolute address of the tracepoint.

Libpatch supports two ways to reference a tracepoint. Either you have the absolute address, in that case the field func_sym must be set to NULL and the field patch_addr can be filled with the absolute address. Otherwise , you must fill func_sym with the name function where the tracepoint is and the instruction offset in insn_offset.

NOTE! The above description mentioned tracepoint as is. But the same is true for would. In other words, referencing to a tracepoint is the same whether the tracepoint exists (already installed) or would exists (trying to install).

NOTE! insn_offset and patch_addr are part of the same anonymous union. You can not use both of them.

Struct: patch_op

Operation to be enqueued. See patch_queue.

.type

Operation type. See patch_op_type.

.addr

Location of tracepoint. See patch_addr.

.probe

Probe to call when hitting the tracepoint. Only necessary when type is PATCH_OP_INSTALL.

.user_data

User data copied in the probe’ context. Only necessary when type is PATCH_OP_INTALL.

.cookie

Unique cookie to reference the enqueued operation. See patch_queue.

NOTE! The operation structure is shared for all type of operation. However, some fields are only necessary for some type of operation.

Struct: patch_result

Result of a enqueued operation after its execution. See patch_commit.

.cookie

Unique cookie of the operation. See patch_queue.

.error

Error during the operation. See patch_err.

.details

Human readable errors of the operation.

2.2 Functions

Function: patch_err patch_init (const patch_opt **opts, size_t opts_cnt)

Initialize the library. This function must be called before calling any other functions.

You can pass an array of options and its size to configure the library.

Returns:

PATCH_OK

If the library was succesfully initialized.

PATCH_ECONF

If an invalid configuration option was passed. In that case, the library is not initialized but it’s possible to call patch_error_string to understand which option failed.

NOTE! It’s not possible to call patch_error_string before the first patch_init!

Function: patch_err patch_fini (void)

Finalize the library. All tracepoints are removed and all allocations made by the library are freed.

Returns:

PATCH_OK

If finalization was done as described above.

PATCH_EFINI

If some finalization failed. Possibly some tracepoints were left behind and some memory areas were leaked.

Function: patch_err patch_configure (const patch_opt *opt)

Configure the library at runtime.

Returns:

PATCH_OK

If option was applied.

PATCH_ENOTSUP

If option is not supported by this version of the library.

PATCH_ECONF

If option is not configurable at runtime.

Function: const char * patch_error_string (void)

Returns an human readable representation of the last error.

You would typically call this function if other functions return something different than PATCH_OK.

NOTE! The string is internal to the library and is only valid until you call a function excepts this one. You probably want to duplicate it somewhere or print it.

Function: patch_err patch_queue (uint64_t flags, patch_op *op)

Enqueue an operation.

Libpatch tries to minimize the synchronization overhead when installing and uninstalling tracepoints. To do so, operations are enqueued and are later executed in batch. We also refer to an enqueued operation as a pending operation.

Returns:

PATCH_OK

Operation was succesfully enqueued. In that case, op->cookie is filled with an unique cookie that can help reference the tracepoint by the application. The cookie can also be used with patch_cancel().

Other

Many error type can be returned. To understand what was the error, use patch_error_string().

NOTE! flags is currently unused and should be set to 0.

Function: patch_err patch_cancel (uint64_t cookie)

Cancel an enqueued operation.

Typically used in an interactive environment, you can cancel an enqueued operation before it was commited with patch_commit().

The cookie is the one filled in the operation structure after calling patch_queue().

Returns:

PATCH_OK

The operation was succesfully canceled.

PATCH_EINVAL

No pending operation is referenced by cookie.

Function: patch_err patch_commit (patch_result **results, size_t *results_count)

Commit all pending operations.

Returns:

PATCH_OK

All pending operations were succesfully done. results_count is filled with 0. This is also the case when there’s no pending operation.

PATCH_EFAIL

Some pending operations have failed. results_count is filled with the number of failed operations. Results of individual failed operations are written in results.

NOTE! results only contains results of failed operations. For example, if you’ve enqueued ten operations and results_count is 1, then results[0] will be the result of the only failed operation.

NOTE! results and results_count are always written to. Thus no matter the returned error value, you must call patch_drop_results() at some point to avoid memory leaks.

Function: patch_err patch_drop_results (patch_result *results)

Free the memory associated with results filled by patch_commit().

Always returns PATCH_OK.

NOTE! No check is made for NULL or that results was allocated by the library.


Next: , Previous: , Up: Top   [Contents][Index]