1.\" 2.\" This file and its contents are supplied under the terms of the 3.\" Common Development and Distribution License ("CDDL"), version 1.0. 4.\" You may only use this file in accordance with the terms of version 5.\" 1.0 of the CDDL. 6.\" 7.\" A full copy of the text of the CDDL should have accompanied this 8.\" source. A copy of the CDDL is also available via the Internet at 9.\" http://www.illumos.org/license/CDDL. 10.\" 11.\" 12.\" Copyright 2023 Oxide Computer Company 13.\" 14.Dd February 15, 2023 15.Dt KTEST_GET_FN 9F 16.Os 17.Sh NAME 18.Nm ktest_get_fn , 19.Nm ktest_hold_mod , 20.Nm ktest_release_mod 21.Nd get a pointer to a static function 22.Sh SYNOPSIS 23.In sys/ktest.h 24.Ft int 25.Fo ktest_get_fn 26.Fa "ddi_modhandle_t hdl" 27.Fa "const char *fn_name" 28.Fa "void **fn" 29.Fc 30.Ft int 31.Fo ktest_hold_mod 32.Fa "const char *module" 33.Fa "ddi_modhandle_t *hdl" 34.Fc 35.Ft void 36.Fo ktest_release_mod 37.Fa "ddi_modhandle_t hdl" 38.Fc 39.Sh INTERFACE LEVEL 40.Sy Volatile - 41This interface is still evolving in illumos. 42API and ABI stability is not guaranteed. 43.Sh PARAMETERS 44.Bl -tag -width Fa 45.It Fa hdl 46A handle to the module. 47.It Fa module 48The name of the module which contains the 49.Ft static 50function you wish to call. 51.It Fa fn_name 52The name of the function. 53.It Fa fn 54A pointer to the function. 55.El 56.Sh DESCRIPTION 57The 58.Fn ktest_get_fn 59function provides the means for accessing private functions (those 60declared with the 61.Ft static 62modifier). 63This is needed when a test module wants to directly test a private 64function. 65.Pp 66In oreder to properly use 67.Fn ktest_get_fn 68there are four steps you must take. 69.Bl -enum 70.It 71Declare a local function pointer with the same type signature as the 72private function you wish to call. 73.It 74Call 75.Fn ktest_hold_mod 76to get a handle to the module containing the private function. 77.It 78Call 79.Fn ktest_get_fn 80to get a pointer to the private function. 81.It 82Make sure to call 83.Fn ktest_release_mod 84as part of test cleanup. 85.El 86.Pp 87First, use a 88.Sy typedef 89to declare a function pointer type with the same signature as the 90private function. 91For example, if the private function has a type signature as follows: 92.Bd -literal -offset 4m 93static uint64_t omnislash(uint64_t level); 94.Ed 95.Pp 96then you should declare a local 97.Sy typedef 98as follows: 99.Bd -literal -offset 4m 100typedef int (*omnislash_t)(uint64_t); 101.Ed 102.Pp 103Notice the use of the "_t" suffix for the typedef. 104With the 105.Sy typedef 106in place you can now easily declare a local function pointer as so: 107.Bd -literal -offset 4m 108omnislash_t omnislash = NULL; 109.Ed 110.Pp 111Next you must call 112.Fn ktest_hold_mod 113to get a handle to the module. 114This also places a hold on the module which acts as an additional 115safety that the function symbol will not go away while the hold 116is outstanding. 117.Pp 118At this point you can now use the module handle to call 119.Fn ktest_get_fn 120to resolve the symbol and fill in the function pointer with the 121correct address. 122Now you can call your local 123.Fn omnislash 124as if it was defined in the test module. 125.Pp 126Finally, you'll want to release the hold as part of test cleanup by 127calling the 128.Fn ktest_release_mod 129function. 130After its completion the function pointer should be considered 131invalid. 132.Pp 133One downside of this approach is that you must be vigilant to 134modifying type signatures of private functions accessed this way. 135The compiler cannot catch a discrepancy in the type signature because 136they are not compiled as a unit. 137It is up to you to make sure the type signature in your test matches 138that of the private function you are calling. 139.Sh RETURN VALUES 140Upon success the 141.Fn ktest_get_fn 142and 143.Fn ktest_hold_mod 144functions return 0. 145Otherwise, these functions return a non-zero value to indicate 146failure. 147The error values returned are not documented because the underlying 148.Xr ddi_modopen 9F 149does not document them. 150.Pp 151The 152.Fn ktest_hold_mod 153function returns the module handle via the 154.Fa hdl 155parameter. 156.Pp 157The 158.Fn ktest_get_fn 159function returns the function pointer via the 160.Fa fn 161parameter. 162.Sh EXAMPLES 163Here's an example of accessing the private function 164.Fn mac_sw_cksum_ipv4 . 165.Bd -literal 166/* 167 * We must declare a local typedef of the private function for 168 * the compiler to generate the call site correctly. 169 */ 170typedef boolean_t (*mac_sw_cksum_ipv4_t)(mblk_t *, uint32_t, ipha_t *, 171 const char **); 172 173void 174private_fn_test(ktest_ctx_hdl_t *ctx) 175{ 176 ddi_modhandle_t hdl = NULL; 177 mac_sw_cksum_ipv4_t mac_sw_cksum_ipv4 = NULL; 178 179 <... other test state ...> 180 181 /* 182 * Get a handle to the module and place a hold on it. 183 */ 184 if (ktest_hold_mod("mac", &hdl) != 0) { 185 KT_ERROR(ctx, "failed to hold 'mac' module"); 186 return; 187 } 188 189 /* 190 * Use the module handle to get a pointer to the private 191 * function. 192 */ 193 if (ktest_get_fn(hdl, "mac_sw_cksum_ipv4", 194 (void **)&mac_sw_cksum_ipv4) != 0) { 195 KT_ERROR(ctx, "failed to resolve symbol " 196 "mac`mac_sw_cksum_ipv4"); 197 goto cleanup; 198 } 199 200 <... test logic ...> 201 202 KT_ASSERT0G(mac_sw_cksum_ipv4(...), ctx, cleanup); 203 KT_PASS(ctx); 204 205cleanup: 206 if (hdl != NULL) { 207 ktest_release_mod(hdl); 208 } 209} 210.Ed 211.Sh SEE ALSO 212.Xr ddi_modopen 9F 213