xref: /illumos-gate/usr/src/man/man9f/ktest_get_fn.9f (revision 8119dad84d6416f13557b0ba8e2aaf9064cbcfd3)
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