KTEST_GET_FN(9F) | Kernel Functions for Drivers | KTEST_GET_FN(9F) |
ktest_get_fn
,
ktest_hold_mod
,
ktest_release_mod
— get a
pointer to a static function
#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);
Volatile - This interface is still evolving in illumos. API and ABI stability is not guaranteed.
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.
ktest_hold_mod
() to get a handle to the
module containing the private function.ktest_get_fn
() to get a pointer to the
private function.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.
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.
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); } }
February 15, 2023 | OmniOS |