Print this page
12046 Provide /proc/<PID>/fdinfo/
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/cmd/sgs/elfdump/common/struct_layout_i386.c
+++ new/usr/src/cmd/sgs/elfdump/common/struct_layout_i386.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 22 /*
23 23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 24 * Use is subject to license terms.
25 25 */
26 26 /*
27 27 * Copyright 2012 DEY Storage Systems, Inc. All rights reserved.
28 28 * Copyright 2018 Joyent, Inc.
29 29 */
30 30
31 31 #include <struct_layout.h>
32 32
33 33
34 34 static const sl_auxv_layout_t auxv_layout = {
35 35 { 0, 8, 0, 0 }, /* sizeof (auxv_t) */
36 36 { 0, 4, 0, 1 }, /* a_type */
37 37 { 4, 4, 0, 1 }, /* a_un.a_val */
38 38 { 4, 4, 0, 0 }, /* a_un.a_ptr */
39 39 { 4, 4, 0, 0 }, /* a_un.a_fcn */
40 40 };
41 41
42 42
43 43 static const sl_prgregset_layout_t prgregset_layout = {
44 44 { 0, 76, 0, 0 }, /* sizeof (prgregset_t) */
45 45 { 0, 4, 19, 0 }, /* elt0 */
46 46 };
47 47
48 48
49 49 static const sl_lwpstatus_layout_t lwpstatus_layout = {
50 50 { 0, 800, 0, 0 }, /* sizeof (lwpstatus_t) */
51 51 { 0, 4, 0, 0 }, /* pr_flags */
52 52 { 4, 4, 0, 0 }, /* pr_lwpid */
53 53 { 8, 2, 0, 0 }, /* pr_why */
54 54 { 10, 2, 0, 0 }, /* pr_what */
55 55 { 12, 2, 0, 0 }, /* pr_cursig */
56 56 { 16, 128, 0, 0 }, /* pr_info */
57 57 { 144, 16, 0, 0 }, /* pr_lwppend */
58 58 { 160, 16, 0, 0 }, /* pr_lwphold */
59 59 { 176, 32, 0, 0 }, /* pr_action */
60 60 { 208, 12, 0, 0 }, /* pr_altstack */
61 61 { 220, 4, 0, 0 }, /* pr_oldcontext */
62 62 { 224, 2, 0, 0 }, /* pr_syscall */
63 63 { 226, 2, 0, 0 }, /* pr_nsysarg */
64 64 { 228, 4, 0, 0 }, /* pr_errno */
65 65 { 232, 4, 8, 0 }, /* pr_sysarg[] */
66 66 { 264, 4, 0, 0 }, /* pr_rval1 */
67 67 { 268, 4, 0, 0 }, /* pr_rval2 */
68 68 { 272, 1, 8, 0 }, /* pr_clname[] */
69 69 { 280, 8, 0, 0 }, /* pr_tstamp */
70 70 { 288, 8, 0, 0 }, /* pr_utime */
71 71 { 296, 8, 0, 0 }, /* pr_stime */
72 72 { 332, 4, 0, 0 }, /* pr_errpriv */
73 73 { 336, 4, 0, 0 }, /* pr_ustack */
74 74 { 340, 4, 0, 0 }, /* pr_instr */
75 75 { 344, 76, 0, 0 }, /* pr_reg */
76 76 { 420, 380, 0, 0 }, /* pr_fpreg */
77 77 };
78 78
79 79
80 80 static const sl_pstatus_layout_t pstatus_layout = {
81 81 { 0, 1136, 0, 0 }, /* sizeof (pstatus_t) */
82 82 { 0, 4, 0, 1 }, /* pr_flags */
83 83 { 4, 4, 0, 1 }, /* pr_nlwp */
84 84 { 8, 4, 0, 0 }, /* pr_pid */
85 85 { 12, 4, 0, 0 }, /* pr_ppid */
86 86 { 16, 4, 0, 0 }, /* pr_pgid */
87 87 { 20, 4, 0, 0 }, /* pr_sid */
88 88 { 24, 4, 0, 1 }, /* pr_aslwpid */
89 89 { 28, 4, 0, 1 }, /* pr_agentid */
90 90 { 32, 16, 0, 0 }, /* pr_sigpend */
91 91 { 48, 4, 0, 0 }, /* pr_brkbase */
92 92 { 52, 4, 0, 0 }, /* pr_brksize */
93 93 { 56, 4, 0, 0 }, /* pr_stkbase */
94 94 { 60, 4, 0, 0 }, /* pr_stksize */
95 95 { 64, 8, 0, 0 }, /* pr_utime */
96 96 { 72, 8, 0, 0 }, /* pr_stime */
97 97 { 80, 8, 0, 0 }, /* pr_cutime */
98 98 { 88, 8, 0, 0 }, /* pr_cstime */
99 99 { 96, 16, 0, 0 }, /* pr_sigtrace */
100 100 { 112, 16, 0, 0 }, /* pr_flttrace */
101 101 { 128, 64, 0, 0 }, /* pr_sysentry */
102 102 { 192, 64, 0, 0 }, /* pr_sysexit */
103 103 { 256, 1, 0, 0 }, /* pr_dmodel */
104 104 { 260, 4, 0, 1 }, /* pr_taskid */
105 105 { 264, 4, 0, 1 }, /* pr_projid */
106 106 { 268, 4, 0, 1 }, /* pr_nzomb */
107 107 { 272, 4, 0, 1 }, /* pr_zoneid */
108 108 { 336, 800, 0, 0 }, /* pr_lwp */
109 109 };
110 110
111 111
112 112 static const sl_prstatus_layout_t prstatus_layout = {
113 113 { 0, 432, 0, 0 }, /* sizeof (prstatus_t) */
114 114 { 0, 4, 0, 1 }, /* pr_flags */
115 115 { 4, 2, 0, 1 }, /* pr_why */
116 116 { 6, 2, 0, 1 }, /* pr_what */
117 117 { 8, 128, 0, 0 }, /* pr_info */
118 118 { 136, 2, 0, 1 }, /* pr_cursig */
119 119 { 138, 2, 0, 0 }, /* pr_nlwp */
120 120 { 140, 16, 0, 0 }, /* pr_sigpend */
121 121 { 156, 16, 0, 0 }, /* pr_sighold */
122 122 { 172, 12, 0, 0 }, /* pr_altstack */
123 123 { 184, 32, 0, 0 }, /* pr_action */
124 124 { 216, 4, 0, 0 }, /* pr_pid */
125 125 { 220, 4, 0, 0 }, /* pr_ppid */
126 126 { 224, 4, 0, 0 }, /* pr_pgrp */
127 127 { 228, 4, 0, 0 }, /* pr_sid */
128 128 { 232, 8, 0, 0 }, /* pr_utime */
129 129 { 240, 8, 0, 0 }, /* pr_stime */
130 130 { 248, 8, 0, 0 }, /* pr_cutime */
131 131 { 256, 8, 0, 0 }, /* pr_cstime */
132 132 { 264, 1, 8, 0 }, /* pr_clname[] */
133 133 { 272, 2, 0, 1 }, /* pr_syscall */
134 134 { 274, 2, 0, 1 }, /* pr_nsysarg */
135 135 { 276, 4, 8, 1 }, /* pr_sysarg[] */
136 136 { 308, 4, 0, 0 }, /* pr_who */
137 137 { 312, 16, 0, 0 }, /* pr_lwppend */
138 138 { 328, 4, 0, 0 }, /* pr_oldcontext */
139 139 { 332, 4, 0, 0 }, /* pr_brkbase */
140 140 { 336, 4, 0, 0 }, /* pr_brksize */
141 141 { 340, 4, 0, 0 }, /* pr_stkbase */
142 142 { 344, 4, 0, 0 }, /* pr_stksize */
143 143 { 348, 2, 0, 1 }, /* pr_processor */
144 144 { 350, 2, 0, 1 }, /* pr_bind */
145 145 { 352, 4, 0, 1 }, /* pr_instr */
146 146 { 356, 76, 0, 0 }, /* pr_reg */
147 147 };
148 148
149 149
150 150 static const sl_psinfo_layout_t psinfo_layout = {
151 151 { 0, 336, 0, 0 }, /* sizeof (psinfo_t) */
152 152 { 0, 4, 0, 1 }, /* pr_flag */
153 153 { 4, 4, 0, 1 }, /* pr_nlwp */
154 154 { 8, 4, 0, 0 }, /* pr_pid */
155 155 { 12, 4, 0, 0 }, /* pr_ppid */
156 156 { 16, 4, 0, 0 }, /* pr_pgid */
157 157 { 20, 4, 0, 0 }, /* pr_sid */
158 158 { 24, 4, 0, 0 }, /* pr_uid */
159 159 { 28, 4, 0, 0 }, /* pr_euid */
160 160 { 32, 4, 0, 0 }, /* pr_gid */
161 161 { 36, 4, 0, 0 }, /* pr_egid */
162 162 { 40, 4, 0, 0 }, /* pr_addr */
163 163 { 44, 4, 0, 0 }, /* pr_size */
164 164 { 48, 4, 0, 0 }, /* pr_rssize */
165 165 { 56, 4, 0, 0 }, /* pr_ttydev */
166 166 { 60, 2, 0, 0 }, /* pr_pctcpu */
167 167 { 62, 2, 0, 0 }, /* pr_pctmem */
168 168 { 64, 8, 0, 0 }, /* pr_start */
169 169 { 72, 8, 0, 0 }, /* pr_time */
170 170 { 80, 8, 0, 0 }, /* pr_ctime */
171 171 { 88, 1, 16, 0 }, /* pr_fname[] */
172 172 { 104, 1, 80, 0 }, /* pr_psargs[] */
173 173 { 184, 4, 0, 1 }, /* pr_wstat */
174 174 { 188, 4, 0, 1 }, /* pr_argc */
175 175 { 192, 4, 0, 0 }, /* pr_argv */
176 176 { 196, 4, 0, 0 }, /* pr_envp */
177 177 { 200, 1, 0, 0 }, /* pr_dmodel */
178 178 { 204, 4, 0, 0 }, /* pr_taskid */
179 179 { 208, 4, 0, 0 }, /* pr_projid */
180 180 { 212, 4, 0, 1 }, /* pr_nzomb */
181 181 { 216, 4, 0, 0 }, /* pr_poolid */
182 182 { 220, 4, 0, 0 }, /* pr_zoneid */
183 183 { 224, 4, 0, 0 }, /* pr_contract */
184 184 { 232, 104, 0, 0 }, /* pr_lwp */
185 185 };
186 186
187 187
188 188 static const sl_prpsinfo_layout_t prpsinfo_layout = {
189 189 { 0, 260, 0, 0 }, /* sizeof (prpsinfo_t) */
190 190 { 0, 1, 0, 0 }, /* pr_state */
191 191 { 1, 1, 0, 0 }, /* pr_sname */
192 192 { 2, 1, 0, 0 }, /* pr_zomb */
193 193 { 3, 1, 0, 0 }, /* pr_nice */
194 194 { 4, 4, 0, 0 }, /* pr_flag */
195 195 { 8, 4, 0, 0 }, /* pr_uid */
196 196 { 12, 4, 0, 0 }, /* pr_gid */
197 197 { 16, 4, 0, 0 }, /* pr_pid */
198 198 { 20, 4, 0, 0 }, /* pr_ppid */
199 199 { 24, 4, 0, 0 }, /* pr_pgrp */
200 200 { 28, 4, 0, 0 }, /* pr_sid */
201 201 { 32, 4, 0, 0 }, /* pr_addr */
202 202 { 36, 4, 0, 0 }, /* pr_size */
203 203 { 40, 4, 0, 0 }, /* pr_rssize */
204 204 { 44, 4, 0, 0 }, /* pr_wchan */
205 205 { 48, 8, 0, 0 }, /* pr_start */
206 206 { 56, 8, 0, 0 }, /* pr_time */
207 207 { 64, 4, 0, 1 }, /* pr_pri */
208 208 { 68, 1, 0, 0 }, /* pr_oldpri */
209 209 { 69, 1, 0, 0 }, /* pr_cpu */
210 210 { 70, 2, 0, 0 }, /* pr_ottydev */
211 211 { 72, 4, 0, 0 }, /* pr_lttydev */
212 212 { 76, 1, 8, 0 }, /* pr_clname[] */
213 213 { 84, 1, 16, 0 }, /* pr_fname[] */
214 214 { 100, 1, 80, 0 }, /* pr_psargs[] */
215 215 { 180, 2, 0, 1 }, /* pr_syscall */
216 216 { 184, 8, 0, 0 }, /* pr_ctime */
217 217 { 192, 4, 0, 0 }, /* pr_bysize */
218 218 { 196, 4, 0, 0 }, /* pr_byrssize */
219 219 { 200, 4, 0, 1 }, /* pr_argc */
220 220 { 204, 4, 0, 0 }, /* pr_argv */
221 221 { 208, 4, 0, 0 }, /* pr_envp */
222 222 { 212, 4, 0, 1 }, /* pr_wstat */
223 223 { 216, 2, 0, 0 }, /* pr_pctcpu */
224 224 { 218, 2, 0, 0 }, /* pr_pctmem */
225 225 { 220, 4, 0, 0 }, /* pr_euid */
226 226 { 224, 4, 0, 0 }, /* pr_egid */
227 227 { 228, 4, 0, 0 }, /* pr_aslwpid */
228 228 { 232, 1, 0, 0 }, /* pr_dmodel */
229 229 };
230 230
231 231
232 232 static const sl_lwpsinfo_layout_t lwpsinfo_layout = {
233 233 { 0, 104, 0, 0 }, /* sizeof (lwpsinfo_t) */
234 234 { 0, 4, 0, 1 }, /* pr_flag */
235 235 { 4, 4, 0, 0 }, /* pr_lwpid */
236 236 { 8, 4, 0, 0 }, /* pr_addr */
237 237 { 12, 4, 0, 0 }, /* pr_wchan */
238 238 { 16, 1, 0, 0 }, /* pr_stype */
239 239 { 17, 1, 0, 0 }, /* pr_state */
240 240 { 18, 1, 0, 0 }, /* pr_sname */
241 241 { 19, 1, 0, 0 }, /* pr_nice */
242 242 { 20, 2, 0, 0 }, /* pr_syscall */
243 243 { 22, 1, 0, 0 }, /* pr_oldpri */
244 244 { 23, 1, 0, 0 }, /* pr_cpu */
245 245 { 24, 4, 0, 1 }, /* pr_pri */
246 246 { 28, 2, 0, 0 }, /* pr_pctcpu */
247 247 { 32, 8, 0, 0 }, /* pr_start */
248 248 { 40, 8, 0, 0 }, /* pr_time */
249 249 { 48, 1, 8, 0 }, /* pr_clname[] */
250 250 { 56, 1, 16, 0 }, /* pr_name[] */
251 251 { 72, 4, 0, 1 }, /* pr_onpro */
252 252 { 76, 4, 0, 1 }, /* pr_bindpro */
253 253 { 80, 4, 0, 1 }, /* pr_bindpset */
254 254 { 84, 4, 0, 1 }, /* pr_lgrp */
255 255 };
256 256
257 257
258 258 static const sl_prcred_layout_t prcred_layout = {
259 259 { 0, 32, 0, 0 }, /* sizeof (prcred_t) */
260 260 { 0, 4, 0, 0 }, /* pr_euid */
261 261 { 4, 4, 0, 0 }, /* pr_ruid */
262 262 { 8, 4, 0, 0 }, /* pr_suid */
263 263 { 12, 4, 0, 0 }, /* pr_egid */
264 264 { 16, 4, 0, 0 }, /* pr_rgid */
265 265 { 20, 4, 0, 0 }, /* pr_sgid */
266 266 { 24, 4, 0, 1 }, /* pr_ngroups */
267 267 { 28, 4, 1, 0 }, /* pr_groups[] */
268 268 };
269 269
270 270
271 271 static const sl_prpriv_layout_t prpriv_layout = {
272 272 { 0, 16, 0, 0 }, /* sizeof (prpriv_t) */
273 273 { 0, 4, 0, 0 }, /* pr_nsets */
274 274 { 4, 4, 0, 0 }, /* pr_setsize */
275 275 { 8, 4, 0, 0 }, /* pr_infosize */
276 276 { 12, 4, 1, 0 }, /* pr_sets[] */
277 277 };
278 278
279 279
280 280 static const sl_priv_impl_info_layout_t priv_impl_info_layout = {
281 281 { 0, 28, 0, 0 }, /* sizeof (priv_impl_info_t) */
282 282 { 0, 4, 0, 0 }, /* priv_headersize */
283 283 { 4, 4, 0, 0 }, /* priv_flags */
284 284 { 8, 4, 0, 0 }, /* priv_nsets */
285 285 { 12, 4, 0, 0 }, /* priv_setsize */
286 286 { 16, 4, 0, 0 }, /* priv_max */
287 287 { 20, 4, 0, 0 }, /* priv_infosize */
288 288 { 24, 4, 0, 0 }, /* priv_globalinfosize */
289 289 };
290 290
291 291
292 292 static const sl_fltset_layout_t fltset_layout = {
293 293 { 0, 16, 0, 0 }, /* sizeof (fltset_t) */
294 294 { 0, 4, 4, 0 }, /* word[] */
295 295 };
296 296
297 297
298 298 static const sl_siginfo_layout_t siginfo_layout = {
299 299 { 0, 128, 0, 0 }, /* sizeof (siginfo_t) */
300 300 { 0, 4, 0, 0 }, /* si_signo */
301 301 { 8, 4, 0, 0 }, /* si_errno */
302 302 { 4, 4, 0, 1 }, /* si_code */
303 303 { 20, 4, 0, 0 }, /* si_value.sival_int */
304 304 { 20, 4, 0, 0 }, /* si_value.sival_ptr */
305 305 { 12, 4, 0, 0 }, /* si_pid */
306 306 { 16, 4, 0, 0 }, /* si_uid */
307 307 { 28, 4, 0, 0 }, /* si_ctid */
308 308 { 32, 4, 0, 0 }, /* si_zoneid */
309 309 { 12, 4, 0, 0 }, /* si_entity */
310 310 { 12, 4, 0, 0 }, /* si_addr */
311 311 { 20, 4, 0, 0 }, /* si_status */
312 312 { 16, 4, 0, 0 }, /* si_band */
313 313 };
314 314
315 315
316 316 static const sl_sigset_layout_t sigset_layout = {
317 317 { 0, 16, 0, 0 }, /* sizeof (sigset_t) */
318 318 { 0, 4, 4, 0 }, /* __sigbits[] */
319 319 };
320 320
321 321
322 322 static const sl_sigaction_layout_t sigaction_layout = {
323 323 { 0, 32, 0, 0 }, /* sizeof (struct sigaction) */
324 324 { 0, 4, 0, 0 }, /* sa_flags */
325 325 { 4, 4, 0, 0 }, /* sa_handler */
326 326 { 4, 4, 0, 0 }, /* sa_sigaction */
327 327 { 8, 16, 0, 0 }, /* sa_mask */
328 328 };
329 329
330 330
331 331 static const sl_stack_layout_t stack_layout = {
332 332 { 0, 12, 0, 0 }, /* sizeof (stack_t) */
333 333 { 0, 4, 0, 0 }, /* ss_sp */
334 334 { 4, 4, 0, 0 }, /* ss_size */
335 335 { 8, 4, 0, 0 }, /* ss_flags */
336 336 };
337 337
338 338
339 339 static const sl_sysset_layout_t sysset_layout = {
340 340 { 0, 64, 0, 0 }, /* sizeof (sysset_t) */
341 341 { 0, 4, 16, 0 }, /* word[] */
342 342 };
343 343
344 344
345 345 static const sl_timestruc_layout_t timestruc_layout = {
346 346 { 0, 8, 0, 0 }, /* sizeof (timestruc_t) */
347 347 { 0, 4, 0, 0 }, /* tv_sec */
348 348 { 4, 4, 0, 0 }, /* tv_nsec */
349 349 };
350 350
351 351
352 352 static const sl_utsname_layout_t utsname_layout = {
↓ open down ↓ |
352 lines elided |
↑ open up ↑ |
353 353 { 0, 1285, 0, 0 }, /* sizeof (struct utsname) */
354 354 { 0, 1, 257, 0 }, /* sysname[] */
355 355 { 257, 1, 257, 0 }, /* nodename[] */
356 356 { 514, 1, 257, 0 }, /* release[] */
357 357 { 771, 1, 257, 0 }, /* version[] */
358 358 { 1028, 1, 257, 0 }, /* machine[] */
359 359 };
360 360
361 361
362 362 static const sl_prfdinfo_layout_t prfdinfo_layout = {
363 - { 0, 1088, 0, 0 }, /* sizeof (prfdinfo_t) */
363 + { 0, 1088, 0, 0 }, /* sizeof (prfdinfov1_t) */
364 364 { 0, 4, 0, 0 }, /* pr_fd */
365 365 { 4, 4, 0, 0 }, /* pr_mode */
366 366 { 8, 4, 0, 0 }, /* pr_uid */
367 367 { 12, 4, 0, 0 }, /* pr_gid */
368 368 { 16, 4, 0, 0 }, /* pr_major */
369 369 { 20, 4, 0, 0 }, /* pr_minor */
370 370 { 24, 4, 0, 0 }, /* pr_rmajor */
371 371 { 28, 4, 0, 0 }, /* pr_rminor */
372 372 { 32, 8, 0, 0 }, /* pr_ino */
373 373 { 40, 8, 0, 0 }, /* pr_offset */
374 374 { 48, 8, 0, 0 }, /* pr_size */
375 375 { 56, 4, 0, 0 }, /* pr_fileflags */
376 376 { 60, 4, 0, 0 }, /* pr_fdflags */
377 377 { 64, 1, 1024, 0 }, /* pr_path[] */
378 378 };
379 379
380 380
381 381 static const sl_prsecflags_layout_t prsecflags_layout = {
382 382 { 0, 40, 0, 0 }, /* sizeof (prsecflags_t) */
383 383 { 0, 4, 0, 0 }, /* pr_version */
384 384 { 8, 8, 0, 0 }, /* pr_effective */
385 385 { 16, 8, 0, 0 }, /* pr_inherit */
386 386 { 24, 8, 0, 0 }, /* pr_lower */
387 387 { 32, 8, 0, 0 }, /* pr_upper */
388 388 };
389 389
390 390
391 391 static const sl_prlwpname_layout_t prlwpname_layout = {
392 392 { 0, 40, 0, 0 }, /* sizeof (prlwpname_t) */
393 393 { 0, 8, 0, 0 }, /* pr_lwpid */
394 394 { 8, 1, 32, 0 }, /* pr_lwpname[] */
395 395 };
396 396
397 397
398 398
399 399
400 400 static const sl_arch_layout_t layout_i386 = {
401 401 &auxv_layout,
402 402 &fltset_layout,
403 403 &lwpsinfo_layout,
404 404 &lwpstatus_layout,
405 405 &prcred_layout,
406 406 &priv_impl_info_layout,
407 407 &prpriv_layout,
408 408 &psinfo_layout,
409 409 &pstatus_layout,
410 410 &prgregset_layout,
411 411 &prpsinfo_layout,
412 412 &prstatus_layout,
413 413 &sigaction_layout,
414 414 &siginfo_layout,
415 415 &sigset_layout,
416 416 &stack_layout,
417 417 &sysset_layout,
418 418 ×truc_layout,
419 419 &utsname_layout,
420 420 &prfdinfo_layout,
421 421 &prsecflags_layout,
422 422 &prlwpname_layout,
423 423 };
424 424
425 425
426 426 const sl_arch_layout_t *
427 427 struct_layout_i386(void)
428 428 {
429 429 return (&layout_i386);
430 430 }
↓ open down ↓ |
57 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX