KTEST_GET_FN(9F) Kernel Functions for Drivers KTEST_GET_FN(9F)
NAME
ktest_get_fn,
ktest_hold_mod,
ktest_release_mod - get a pointer to a
static function
SYNOPSIS
#include <sys/ktest.h> int ktest_get_fn(
ddi_modhandle_t hdl,
const char *fn_name,
void **fn);
int ktest_hold_mod(
const char *module,
ddi_modhandle_t *hdl);
void ktest_release_mod(
ddi_modhandle_t hdl);
INTERFACE LEVEL
Volatile - This interface is still evolving in illumos. API and ABI
stability is not guaranteed.
PARAMETERS
hdl A handle to the module.
module The name of the module which contains the
static function
you wish to call.
fn_name The name of the function.
fn A pointer to the function.
DESCRIPTION
The
ktest_get_fn() function provides the means for accessing private
functions (those declared with the
static modifier). This is needed
when a test module wants to directly test a private function.
In oreder to properly use
ktest_get_fn() there are four steps you must
take.
1. Declare a local function pointer with the same type signature as
the private function you wish to call.
2. Call
ktest_hold_mod() to get a handle to the module containing the
private function.
3. Call
ktest_get_fn() to get a pointer to the private function.
4. Make sure to call
ktest_release_mod() as part of test cleanup.
First, use a
typedef to declare a function pointer type with the same
signature as the private function. For example, if the private
function has a type signature as follows:
static uint64_t omnislash(uint64_t level);
then you should declare a local
typedef as follows:
typedef int (*omnislash_t)(uint64_t);
Notice the use of the "_t" suffix for the typedef. With the
typedef in
place you can now easily declare a local function pointer as so:
omnislash_t omnislash = NULL;
Next you must call
ktest_hold_mod() to get a handle to the module.
This also places a hold on the module which acts as an additional
safety that the function symbol will not go away while the hold is
outstanding.
At this point you can now use the module handle to call
ktest_get_fn()
to resolve the symbol and fill in the function pointer with the correct
address. Now you can call your local
omnislash() as if it was defined
in the test module.
Finally, you'll want to release the hold as part of test cleanup by
calling the
ktest_release_mod() function. After its completion the
function pointer should be considered invalid.
One downside of this approach is that you must be vigilant to modifying
type signatures of private functions accessed this way. The compiler
cannot catch a discrepancy in the type signature because they are not
compiled as a unit. It is up to you to make sure the type signature in
your test matches that of the private function you are calling.
RETURN VALUES
Upon success the
ktest_get_fn() and
ktest_hold_mod() functions return
0. Otherwise, these functions return a non-zero value to indicate
failure. The error values returned are not documented because the
underlying
ddi_modopen(9F) does not document them.
The
ktest_hold_mod() function returns the module handle via the
hdl parameter.
The
ktest_get_fn() function returns the function pointer via the
fn parameter.
EXAMPLES
Here's an example of accessing the private function
mac_sw_cksum_ipv4().
/*
* We must declare a local typedef of the private function for
* the compiler to generate the call site correctly.
*/
typedef boolean_t (*mac_sw_cksum_ipv4_t)(mblk_t *, uint32_t, ipha_t *,
const char **);
void
private_fn_test(ktest_ctx_hdl_t *ctx)
{
ddi_modhandle_t hdl = NULL;
mac_sw_cksum_ipv4_t mac_sw_cksum_ipv4 = NULL;
<... other test state ...>
/*
* Get a handle to the module and place a hold on it.
*/
if (ktest_hold_mod("mac", &hdl) != 0) {
KT_ERROR(ctx, "failed to hold 'mac' module");
return;
}
/*
* Use the module handle to get a pointer to the private
* function.
*/
if (ktest_get_fn(hdl, "mac_sw_cksum_ipv4",
(void **)&mac_sw_cksum_ipv4) != 0) {
KT_ERROR(ctx, "failed to resolve symbol "
"mac`mac_sw_cksum_ipv4");
goto cleanup;
}
<... test logic ...>
KT_ASSERT0G(mac_sw_cksum_ipv4(...), ctx, cleanup);
KT_PASS(ctx);
cleanup:
if (hdl != NULL) {
ktest_release_mod(hdl);
}
}
SEE ALSO
ddi_modopen(9F)illumos February 15, 2023 illumos