Next: Implementation Details, Previous: Introduction, Up: Top [Contents][Index]
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> }
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.
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.
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.
Function to execute when hitting a tracepoint.
The signature is void (*)(struct patch_probe_context *)
.
Architecture dependent unsigned integer value for a register.
Number of general registers that are in the gregs
field of a
patch_probe_context
struct.
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.
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" } };
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.
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.
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.
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.
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
!
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.
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.
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.
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
.
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.
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.
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: Implementation Details, Previous: Introduction, Up: Top [Contents][Index]