xref: /illumos-gate/usr/src/cmd/sgs/elfdump/common/gen_struct_layout.c (revision a52121ea720d327228a95e9d0c4a426339f08c7f)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  *
26  * Copyright 2015 Nexenta Systems, Inc.  All rights reserved.
27  * Copyright 2018 Joyent, Inc.
28  * Copyright 2020 OmniOS Community Edition (OmniOSce) Association.
29  */
30 
31 /*
32  * This program is used to generate the contents of the
33  * struct_layout_XXX.c files that contain per-architecture
34  * structure layout information.
35  *
36  * Although not part of elfdump, it is built by the makefile
37  * along with it.
38  * To use it:
39  *
40  *	1) Run it, capturing the output in a file.
41  *	2) If this is a replacement for an existing file,
42  *		diff the new and old copies to ensure only
43  *		the changes you expected are present.
44  *	3) Put the new file in the common directory under the name
45  *		struct_layout_XXX.c, where XXX is the name of
46  *		the architecture (i386, amd64, sparc, sparcv9, etc).
47  *	2) Add any necessary header and copyright comments.
48  *	3) If this is a new architecture:
49  *		- Add an extern statement for struct_layout_XXX()
50  *			to struct_layout.h
51  *		- Add a case for it to the function sl_struct_layout()
52  *			in struct_layout.c.
53  */
54 
55 #include <string.h>
56 #include <stdio.h>
57 #include <stdlib.h>
58 #include <ctype.h>
59 #include <err.h>
60 #include <sys/types.h>
61 #include <libctf.h>
62 
63 /*
64  * This extracts CTF information from a temporary object file.
65  *
66  * START and END bracket a struct layout definition. They issue
67  * the typedef boilerplate, and the standard first element (sizeof)
68  * which captures the overall size of the structure.
69  *
70  * SCALAR_FIELD is for scalar struct fields
71  *
72  * ARRAY_FIELD is for  array struct fields
73  *
74  * ARRAY_TYPE is for plain (non-struct) array types
75  */
76 #define	START(_name, _type) \
77 	do_start(#_name, #_type)
78 #define	END (void) \
79 	do_end()
80 #define	SCALAR_FIELD(_type, _field, _sign) \
81 	do_scalar_field(#_type, #_field, _sign, NULL)
82 #define	SCALAR_FIELD4(_type, _field, _sign, _rtype) \
83 	do_scalar_field(#_type, #_field, _sign, _rtype)
84 #define	ARRAY_FIELD(_type, _field, _sign) \
85 	do_array_field(#_type, #_field, _sign, NULL)
86 #define	ARRAY_TYPE(_type, _sign) \
87 	do_array_type(#_type, "elt0", _sign)
88 
89 static void do_start(char *_name, char *_type);
90 static void do_end(void);
91 static void do_start_name(char *name);
92 static void do_start_sizeof(char *_type, char *realtype);
93 static void do_scalar_field(char *_type, char *_field,
94 	int _sign, char *dotfield);
95 static void do_array_field(char *_type, char *_field,
96 	int _sign, char *dotfield);
97 static void do_array_type(char *_type, char *_field, int _sign);
98 
99 static void get_ctf_file(char *fname);
100 static int get_field_info(char *tname, char *fname, char *dotname,
101 	int *offp, int *sizep);
102 
103 static ctf_file_t *ctf;
104 static char *objfile;
105 static char *machname;
106 
107 /* auxv_t, <sys/auxv.h> */
108 static void
109 gen_auxv(void)
110 {
111 	START(auxv, auxv_t);
112 
113 	SCALAR_FIELD(auxv_t,	a_type,	1);
114 	SCALAR_FIELD(auxv_t,	a_un.a_val,	1);
115 	SCALAR_FIELD(auxv_t,	a_un.a_ptr,	0);
116 	SCALAR_FIELD(auxv_t,	a_un.a_fcn,	0);
117 
118 	END;
119 }
120 
121 
122 /* prgregset_t, <sys/prgregset.h> */
123 static void
124 gen_prgregset(void)
125 {
126 	START(prgregset, prgregset_t);
127 
128 	ARRAY_TYPE(prgregset_t,	0);
129 
130 	END;
131 }
132 
133 
134 /* lwpstatus_t, <sys/procfs.h> */
135 static void
136 gen_lwpstatus(void)
137 {
138 	START(lwpstatus, lwpstatus_t);
139 
140 	SCALAR_FIELD(lwpstatus_t,	pr_flags,	0);
141 	SCALAR_FIELD(lwpstatus_t,	pr_lwpid,	0);
142 	SCALAR_FIELD(lwpstatus_t,	pr_why,		0);
143 	SCALAR_FIELD(lwpstatus_t,	pr_what,	0);
144 	SCALAR_FIELD(lwpstatus_t,	pr_cursig,	0);
145 	SCALAR_FIELD(lwpstatus_t,	pr_info,	0);
146 	SCALAR_FIELD(lwpstatus_t,	pr_lwppend,	0);
147 	SCALAR_FIELD(lwpstatus_t,	pr_lwphold,	0);
148 	SCALAR_FIELD(lwpstatus_t,	pr_action,	0);
149 	SCALAR_FIELD(lwpstatus_t,	pr_altstack,	0);
150 	SCALAR_FIELD(lwpstatus_t,	pr_oldcontext,	0);
151 	SCALAR_FIELD(lwpstatus_t,	pr_syscall,	0);
152 	SCALAR_FIELD(lwpstatus_t,	pr_nsysarg,	0);
153 	SCALAR_FIELD(lwpstatus_t,	pr_errno,	0);
154 	ARRAY_FIELD(lwpstatus_t,	pr_sysarg,	0);
155 	SCALAR_FIELD(lwpstatus_t,	pr_rval1,	0);
156 	SCALAR_FIELD(lwpstatus_t,	pr_rval2,	0);
157 	ARRAY_FIELD(lwpstatus_t,	pr_clname,	0);
158 	SCALAR_FIELD(lwpstatus_t,	pr_tstamp,	0);
159 	SCALAR_FIELD(lwpstatus_t,	pr_utime,	0);
160 	SCALAR_FIELD(lwpstatus_t,	pr_stime,	0);
161 	SCALAR_FIELD(lwpstatus_t,	pr_errpriv,	0);
162 	SCALAR_FIELD(lwpstatus_t,	pr_ustack,	0);
163 	SCALAR_FIELD(lwpstatus_t,	pr_instr,	0);
164 	SCALAR_FIELD(lwpstatus_t,	pr_reg,		0);
165 	SCALAR_FIELD(lwpstatus_t,	pr_fpreg,	0);
166 
167 	END;
168 }
169 
170 
171 /* pstatus_t, <sys/procfs.h> */
172 static void
173 gen_pstatus(void)
174 {
175 	START(pstatus, pstatus_t);
176 
177 	SCALAR_FIELD(pstatus_t,		pr_flags,	1);
178 	SCALAR_FIELD(pstatus_t,		pr_nlwp,	1);
179 	SCALAR_FIELD(pstatus_t,		pr_pid,		0);
180 	SCALAR_FIELD(pstatus_t,		pr_ppid,	0);
181 	SCALAR_FIELD(pstatus_t,		pr_pgid,	0);
182 	SCALAR_FIELD(pstatus_t,		pr_sid,		0);
183 	SCALAR_FIELD(pstatus_t,		pr_aslwpid,	1);
184 	SCALAR_FIELD(pstatus_t,		pr_agentid,	1);
185 	SCALAR_FIELD(pstatus_t,		pr_sigpend,	0);
186 	SCALAR_FIELD(pstatus_t,		pr_brkbase,	0);
187 	SCALAR_FIELD(pstatus_t,		pr_brksize,	0);
188 	SCALAR_FIELD(pstatus_t,		pr_stkbase,	0);
189 	SCALAR_FIELD(pstatus_t,		pr_stksize,	0);
190 	SCALAR_FIELD(pstatus_t,		pr_utime,	0);
191 	SCALAR_FIELD(pstatus_t,		pr_stime,	0);
192 	SCALAR_FIELD(pstatus_t,		pr_cutime,	0);
193 	SCALAR_FIELD(pstatus_t,		pr_cstime,	0);
194 	SCALAR_FIELD(pstatus_t,		pr_sigtrace,	0);
195 	SCALAR_FIELD(pstatus_t,		pr_flttrace,	0);
196 	SCALAR_FIELD(pstatus_t,		pr_sysentry,	0);
197 	SCALAR_FIELD(pstatus_t,		pr_sysexit,	0);
198 	SCALAR_FIELD(pstatus_t,		pr_dmodel,	0);
199 	SCALAR_FIELD(pstatus_t,		pr_taskid,	1);
200 	SCALAR_FIELD(pstatus_t,		pr_projid,	1);
201 	SCALAR_FIELD(pstatus_t,		pr_nzomb,	1);
202 	SCALAR_FIELD(pstatus_t,		pr_zoneid,	1);
203 	SCALAR_FIELD(pstatus_t,		pr_lwp,		0);
204 
205 	END;
206 }
207 
208 
209 /* prstatus_t, <sys/old_procfs.h> */
210 static void
211 gen_prstatus(void)
212 {
213 	START(prstatus, prstatus_t);
214 
215 	SCALAR_FIELD(prstatus_t,	pr_flags,	1);
216 	SCALAR_FIELD(prstatus_t,	pr_why,		1);
217 	SCALAR_FIELD(prstatus_t,	pr_what,	1);
218 	SCALAR_FIELD(prstatus_t,	pr_info,	0);
219 	SCALAR_FIELD(prstatus_t,	pr_cursig,	1);
220 	SCALAR_FIELD(prstatus_t,	pr_nlwp,	0);
221 	SCALAR_FIELD(prstatus_t,	pr_sigpend,	0);
222 	SCALAR_FIELD(prstatus_t,	pr_sighold,	0);
223 	SCALAR_FIELD(prstatus_t,	pr_altstack,	0);
224 	SCALAR_FIELD(prstatus_t,	pr_action,	0);
225 	SCALAR_FIELD(prstatus_t,	pr_pid,		0);
226 	SCALAR_FIELD(prstatus_t,	pr_ppid,	0);
227 	SCALAR_FIELD(prstatus_t,	pr_pgrp,	0);
228 	SCALAR_FIELD(prstatus_t,	pr_sid,		0);
229 	SCALAR_FIELD(prstatus_t,	pr_utime,	0);
230 	SCALAR_FIELD(prstatus_t,	pr_stime,	0);
231 	SCALAR_FIELD(prstatus_t,	pr_cutime,	0);
232 	SCALAR_FIELD(prstatus_t,	pr_cstime,	0);
233 	ARRAY_FIELD(prstatus_t,		pr_clname,	0);
234 	SCALAR_FIELD(prstatus_t,	pr_syscall,	1);
235 	SCALAR_FIELD(prstatus_t,	pr_nsysarg,	1);
236 	ARRAY_FIELD(prstatus_t,		pr_sysarg,	1);
237 	SCALAR_FIELD(prstatus_t,	pr_who,		0);
238 	SCALAR_FIELD(prstatus_t,	pr_lwppend,	0);
239 	SCALAR_FIELD(prstatus_t,	pr_oldcontext,	0);
240 	SCALAR_FIELD(prstatus_t,	pr_brkbase,	0);
241 	SCALAR_FIELD(prstatus_t,	pr_brksize,	0);
242 	SCALAR_FIELD(prstatus_t,	pr_stkbase,	0);
243 	SCALAR_FIELD(prstatus_t,	pr_stksize,	0);
244 	SCALAR_FIELD(prstatus_t,	pr_processor,	1);
245 	SCALAR_FIELD(prstatus_t,	pr_bind,	1);
246 	SCALAR_FIELD(prstatus_t,	pr_instr,	1);
247 	SCALAR_FIELD(prstatus_t,	pr_reg,		0);
248 
249 	END;
250 }
251 
252 
253 /* psinfo_t, <sys/procfs.h> */
254 static void
255 gen_psinfo(void)
256 {
257 	START(psinfo, psinfo_t);
258 
259 	SCALAR_FIELD(psinfo_t,		pr_flag,	1);
260 	SCALAR_FIELD(psinfo_t,		pr_nlwp,	1);
261 	SCALAR_FIELD(psinfo_t,		pr_pid,		0);
262 	SCALAR_FIELD(psinfo_t,		pr_ppid,	0);
263 	SCALAR_FIELD(psinfo_t,		pr_pgid,	0);
264 	SCALAR_FIELD(psinfo_t,		pr_sid,		0);
265 	SCALAR_FIELD(psinfo_t,		pr_uid,		0);
266 	SCALAR_FIELD(psinfo_t,		pr_euid,	0);
267 	SCALAR_FIELD(psinfo_t,		pr_gid,		0);
268 	SCALAR_FIELD(psinfo_t,		pr_egid,	0);
269 	SCALAR_FIELD(psinfo_t,		pr_addr,	0);
270 	SCALAR_FIELD(psinfo_t,		pr_size,	0);
271 	SCALAR_FIELD(psinfo_t,		pr_rssize,	0);
272 	SCALAR_FIELD(psinfo_t,		pr_ttydev,	0);
273 	SCALAR_FIELD(psinfo_t,		pr_pctcpu,	0);
274 	SCALAR_FIELD(psinfo_t,		pr_pctmem,	0);
275 	SCALAR_FIELD(psinfo_t,		pr_start,	0);
276 	SCALAR_FIELD(psinfo_t,		pr_time,	0);
277 	SCALAR_FIELD(psinfo_t,		pr_ctime,	0);
278 	ARRAY_FIELD(psinfo_t,		pr_fname,	0);
279 	ARRAY_FIELD(psinfo_t,		pr_psargs,	0);
280 	SCALAR_FIELD(psinfo_t,		pr_wstat,	1);
281 	SCALAR_FIELD(psinfo_t,		pr_argc,	1);
282 	SCALAR_FIELD(psinfo_t,		pr_argv,	0);
283 	SCALAR_FIELD(psinfo_t,		pr_envp,	0);
284 	SCALAR_FIELD(psinfo_t,		pr_dmodel,	0);
285 	SCALAR_FIELD(psinfo_t,		pr_taskid,	0);
286 	SCALAR_FIELD(psinfo_t,		pr_projid,	0);
287 	SCALAR_FIELD(psinfo_t,		pr_nzomb,	1);
288 	SCALAR_FIELD(psinfo_t,		pr_poolid,	0);
289 	SCALAR_FIELD(psinfo_t,		pr_zoneid,	0);
290 	SCALAR_FIELD(psinfo_t,		pr_contract,	0);
291 	SCALAR_FIELD(psinfo_t,		pr_lwp,		0);
292 
293 	END;
294 }
295 
296 /* prpsinfo_t, <sys/old_procfs.h> */
297 static void
298 gen_prpsinfo(void)
299 {
300 	START(prpsinfo, prpsinfo_t);
301 
302 	SCALAR_FIELD(prpsinfo_t,	pr_state,	0);
303 	SCALAR_FIELD(prpsinfo_t,	pr_sname,	0);
304 	SCALAR_FIELD(prpsinfo_t,	pr_zomb,	0);
305 	SCALAR_FIELD(prpsinfo_t,	pr_nice,	0);
306 	SCALAR_FIELD(prpsinfo_t,	pr_flag,	0);
307 	SCALAR_FIELD(prpsinfo_t,	pr_uid,		0);
308 	SCALAR_FIELD(prpsinfo_t,	pr_gid,		0);
309 	SCALAR_FIELD(prpsinfo_t,	pr_pid,		0);
310 	SCALAR_FIELD(prpsinfo_t,	pr_ppid,	0);
311 	SCALAR_FIELD(prpsinfo_t,	pr_pgrp,	0);
312 	SCALAR_FIELD(prpsinfo_t,	pr_sid,		0);
313 	SCALAR_FIELD(prpsinfo_t,	pr_addr,	0);
314 	SCALAR_FIELD(prpsinfo_t,	pr_size,	0);
315 	SCALAR_FIELD(prpsinfo_t,	pr_rssize,	0);
316 	SCALAR_FIELD(prpsinfo_t,	pr_wchan,	0);
317 	SCALAR_FIELD(prpsinfo_t,	pr_start,	0);
318 	SCALAR_FIELD(prpsinfo_t,	pr_time,	0);
319 	SCALAR_FIELD(prpsinfo_t,	pr_pri,		1);
320 	SCALAR_FIELD(prpsinfo_t,	pr_oldpri,	0);
321 	SCALAR_FIELD(prpsinfo_t,	pr_cpu,		0);
322 	SCALAR_FIELD(prpsinfo_t,	pr_ottydev,	0);
323 	SCALAR_FIELD(prpsinfo_t,	pr_lttydev,	0);
324 	ARRAY_FIELD(prpsinfo_t,		pr_clname,	0);
325 	ARRAY_FIELD(prpsinfo_t,		pr_fname,	0);
326 	ARRAY_FIELD(prpsinfo_t,		pr_psargs,	0);
327 	SCALAR_FIELD(prpsinfo_t,	pr_syscall,	1);
328 	SCALAR_FIELD(prpsinfo_t,	pr_ctime,	0);
329 	SCALAR_FIELD(prpsinfo_t,	pr_bysize,	0);
330 	SCALAR_FIELD(prpsinfo_t,	pr_byrssize,	0);
331 	SCALAR_FIELD(prpsinfo_t,	pr_argc,	1);
332 	SCALAR_FIELD(prpsinfo_t,	pr_argv,	0);
333 	SCALAR_FIELD(prpsinfo_t,	pr_envp,	0);
334 	SCALAR_FIELD(prpsinfo_t,	pr_wstat,	1);
335 	SCALAR_FIELD(prpsinfo_t,	pr_pctcpu,	0);
336 	SCALAR_FIELD(prpsinfo_t,	pr_pctmem,	0);
337 	SCALAR_FIELD(prpsinfo_t,	pr_euid,	0);
338 	SCALAR_FIELD(prpsinfo_t,	pr_egid,	0);
339 	SCALAR_FIELD(prpsinfo_t,	pr_aslwpid,	0);
340 	SCALAR_FIELD(prpsinfo_t,	pr_dmodel,	0);
341 
342 	END;
343 }
344 
345 /* lwpsinfo_t, <sys/procfs.h> */
346 static void
347 gen_lwpsinfo(void)
348 {
349 	START(lwpsinfo, lwpsinfo_t);
350 
351 	SCALAR_FIELD(lwpsinfo_t,	pr_flag,	1);
352 	SCALAR_FIELD(lwpsinfo_t,	pr_lwpid,	0);
353 	SCALAR_FIELD(lwpsinfo_t,	pr_addr,	0);
354 	SCALAR_FIELD(lwpsinfo_t,	pr_wchan,	0);
355 	SCALAR_FIELD(lwpsinfo_t,	pr_stype,	0);
356 	SCALAR_FIELD(lwpsinfo_t,	pr_state,	0);
357 	SCALAR_FIELD(lwpsinfo_t,	pr_sname,	0);
358 	SCALAR_FIELD(lwpsinfo_t,	pr_nice,	0);
359 	SCALAR_FIELD(lwpsinfo_t,	pr_syscall,	0);
360 	SCALAR_FIELD(lwpsinfo_t,	pr_oldpri,	0);
361 	SCALAR_FIELD(lwpsinfo_t,	pr_cpu,		0);
362 	SCALAR_FIELD(lwpsinfo_t,	pr_pri,		1);
363 	SCALAR_FIELD(lwpsinfo_t,	pr_pctcpu,	0);
364 	SCALAR_FIELD(lwpsinfo_t,	pr_start,	0);
365 	SCALAR_FIELD(lwpsinfo_t,	pr_time,	0);
366 	ARRAY_FIELD(lwpsinfo_t,		pr_clname,	0);
367 	ARRAY_FIELD(lwpsinfo_t,		pr_name,	0);
368 	SCALAR_FIELD(lwpsinfo_t,	pr_onpro,	1);
369 	SCALAR_FIELD(lwpsinfo_t,	pr_bindpro,	1);
370 	SCALAR_FIELD(lwpsinfo_t,	pr_bindpset,	1);
371 	SCALAR_FIELD(lwpsinfo_t,	pr_lgrp,	1);
372 
373 	END;
374 }
375 
376 /* prcred_t, <sys/procfs.h> */
377 static void
378 gen_prcred(void)
379 {
380 	START(prcred, prcred_t);
381 
382 	SCALAR_FIELD(prcred_t,		pr_euid,	0);
383 	SCALAR_FIELD(prcred_t,		pr_ruid,	0);
384 	SCALAR_FIELD(prcred_t,		pr_suid,	0);
385 	SCALAR_FIELD(prcred_t,		pr_egid,	0);
386 	SCALAR_FIELD(prcred_t,		pr_rgid,	0);
387 	SCALAR_FIELD(prcred_t,		pr_sgid,	0);
388 	SCALAR_FIELD(prcred_t,		pr_ngroups,	1);
389 	ARRAY_FIELD(prcred_t,		pr_groups,	0);
390 
391 	END;
392 }
393 
394 /* prpriv_t, <sys/procfs.h> */
395 static void
396 gen_prpriv(void)
397 {
398 	START(prpriv, prpriv_t);
399 
400 	SCALAR_FIELD(prpriv_t,		pr_nsets,	0);
401 	SCALAR_FIELD(prpriv_t,		pr_setsize,	0);
402 	SCALAR_FIELD(prpriv_t,		pr_infosize,	0);
403 	ARRAY_FIELD(prpriv_t,		pr_sets,	0);
404 
405 	END;
406 }
407 
408 
409 /* priv_impl_info_t, <sys/priv.h> */
410 static void
411 gen_priv_impl_info(void)
412 {
413 	START(priv_impl_info, priv_impl_info_t);
414 
415 	SCALAR_FIELD(priv_impl_info_t,	priv_headersize,	0);
416 	SCALAR_FIELD(priv_impl_info_t,	priv_flags,		0);
417 	SCALAR_FIELD(priv_impl_info_t,	priv_nsets,		0);
418 	SCALAR_FIELD(priv_impl_info_t,	priv_setsize,		0);
419 	SCALAR_FIELD(priv_impl_info_t,	priv_max,		0);
420 	SCALAR_FIELD(priv_impl_info_t,	priv_infosize,		0);
421 	SCALAR_FIELD(priv_impl_info_t,	priv_globalinfosize,	0);
422 
423 	END;
424 }
425 
426 
427 /* fltset_t, <sys/fault.h> */
428 static void
429 gen_fltset(void)
430 {
431 	START(fltset, fltset_t);
432 
433 	ARRAY_FIELD(fltset_t,	word,	0);
434 
435 	END;
436 }
437 
438 /*
439  * Layout description of siginfo_t, <sys/siginfo.h>
440  *
441  * Note: many siginfo_t members are #defines mapping to
442  * long dotted members of sub-structs or unions, and
443  * we need the full member spec (with dots) for those.
444  */
445 static void
446 gen_siginfo(void)
447 {
448 	START(siginfo, siginfo_t);
449 
450 	SCALAR_FIELD(siginfo_t,		si_signo,		0);
451 	SCALAR_FIELD(siginfo_t,		si_errno,		0);
452 	SCALAR_FIELD(siginfo_t,		si_code,		1);
453 
454 	SCALAR_FIELD4(siginfo_t,	si_value.sival_int,	0,
455 	    "__data.__proc.__pdata.__kill.__value.sival_int");
456 
457 	SCALAR_FIELD4(siginfo_t,	si_value.sival_ptr,	0,
458 	    "__data.__proc.__pdata.__kill.__value.sival_ptr");
459 
460 	SCALAR_FIELD4(siginfo_t,	si_pid,			0,
461 	    "__data.__proc.__pid");
462 
463 	SCALAR_FIELD4(siginfo_t,	si_uid,			0,
464 	    "__data.__proc.__pdata.__kill.__uid");
465 
466 	SCALAR_FIELD4(siginfo_t,	si_ctid,		0,
467 	    "__data.__proc.__ctid");
468 
469 	SCALAR_FIELD4(siginfo_t,	si_zoneid,		0,
470 	    "__data.__proc.__zoneid");
471 
472 	SCALAR_FIELD4(siginfo_t,	si_entity,		0,
473 	    "__data.__rctl.__entity");
474 
475 	SCALAR_FIELD4(siginfo_t,	si_addr,		0,
476 	    "__data.__fault.__addr");
477 
478 	SCALAR_FIELD4(siginfo_t,	si_status,		0,
479 	    "__data.__proc.__pdata.__cld.__status");
480 
481 	SCALAR_FIELD4(siginfo_t,	si_band,		0,
482 	    "__data.__file.__band");
483 
484 	END;
485 }
486 
487 /* sigset_t, <sys/signal.h> */
488 static void
489 gen_sigset(void)
490 {
491 	START(sigset, sigset_t);
492 
493 	ARRAY_FIELD(sigset_t,	__sigbits,	0);
494 
495 	END;
496 }
497 
498 
499 /* struct sigaction, <sys/signal.h> */
500 static void
501 gen_sigaction(void)
502 {
503 	START(sigaction, struct sigaction);
504 
505 	SCALAR_FIELD(struct sigaction,	sa_flags,	0);
506 
507 	SCALAR_FIELD4(struct sigaction,	sa_handler,	0,
508 	    "_funcptr._handler");
509 
510 	SCALAR_FIELD4(struct sigaction,	sa_sigaction,	0,
511 	    "_funcptr._sigaction");
512 
513 	SCALAR_FIELD(struct sigaction,	sa_mask,	0);
514 
515 	END;
516 }
517 
518 /* stack_t, <sys/signal.h> */
519 static void
520 gen_stack(void)
521 {
522 	START(stack, stack_t);
523 
524 	SCALAR_FIELD(stack_t,	ss_sp,		0);
525 	SCALAR_FIELD(stack_t,	ss_size,	0);
526 	SCALAR_FIELD(stack_t,	ss_flags,	0);
527 
528 	END;
529 }
530 
531 /* sysset_t, <sys/syscall.h> */
532 static void
533 gen_sysset(void)
534 {
535 	START(sysset, sysset_t);
536 
537 	ARRAY_FIELD(sysset_t,	word,	0);
538 
539 	END;
540 }
541 
542 /* timestruc_t, <sys/time_impl.h> */
543 static void
544 gen_timestruc(void)
545 {
546 	START(timestruc, timestruc_t);
547 
548 	SCALAR_FIELD(timestruc_t,	tv_sec,		0);
549 	SCALAR_FIELD(timestruc_t,	tv_nsec,	0);
550 
551 	END;
552 }
553 
554 /* struct utsname, <sys/utsname.h> */
555 static void
556 gen_utsname(void)
557 {
558 	START(utsname, struct utsname);
559 
560 	ARRAY_FIELD(struct utsname,	sysname,	0);
561 	ARRAY_FIELD(struct utsname,	nodename,	0);
562 	ARRAY_FIELD(struct utsname,	release,	0);
563 	ARRAY_FIELD(struct utsname,	version,	0);
564 	ARRAY_FIELD(struct utsname,	machine,	0);
565 
566 	END;
567 }
568 
569 static void
570 gen_prfdinfo(void)
571 {
572 	START(prfdinfo, prfdinfo_core_t);
573 
574 	SCALAR_FIELD(prfdinfo_core_t,	pr_fd,		0);
575 	SCALAR_FIELD(prfdinfo_core_t,	pr_mode,	0);
576 	SCALAR_FIELD(prfdinfo_core_t,	pr_uid,		0);
577 	SCALAR_FIELD(prfdinfo_core_t,	pr_gid,		0);
578 	SCALAR_FIELD(prfdinfo_core_t,	pr_major,	0);
579 	SCALAR_FIELD(prfdinfo_core_t,	pr_minor,	0);
580 	SCALAR_FIELD(prfdinfo_core_t,	pr_rmajor,	0);
581 	SCALAR_FIELD(prfdinfo_core_t,	pr_rminor,	0);
582 	SCALAR_FIELD(prfdinfo_core_t,	pr_ino,		0);
583 	SCALAR_FIELD(prfdinfo_core_t,	pr_offset,	0);
584 	SCALAR_FIELD(prfdinfo_core_t,	pr_size,	0);
585 	SCALAR_FIELD(prfdinfo_core_t,	pr_fileflags,	0);
586 	SCALAR_FIELD(prfdinfo_core_t,	pr_fdflags,	0);
587 	ARRAY_FIELD(prfdinfo_core_t,	pr_path,	0);
588 
589 	END;
590 }
591 
592 static void
593 gen_prsecflags(void)
594 {
595 	START(prsecflags, prsecflags_t);
596 	SCALAR_FIELD(prsecflags_t, pr_version, 0);
597 	SCALAR_FIELD(prsecflags_t, pr_effective, 0);
598 	SCALAR_FIELD(prsecflags_t, pr_inherit, 0);
599 	SCALAR_FIELD(prsecflags_t, pr_lower, 0);
600 	SCALAR_FIELD(prsecflags_t, pr_upper, 0);
601 	END;
602 }
603 
604 static void
605 gen_prlwpname(void)
606 {
607 	START(prlwpname, prlwpname_t);
608 	SCALAR_FIELD(prlwpname_t, pr_lwpid, 0);
609 	ARRAY_FIELD(prlwpname_t, pr_lwpname, 0);
610 	END;
611 }
612 
613 /*ARGSUSED*/
614 int
615 main(int argc, char *argv[])
616 {
617 	const char *fmt = "\t&%s_layout,\n";
618 
619 	/* get obj file for input */
620 	if (argc < 3) {
621 		(void) fprintf(stderr,
622 		    "usage: %s {object_file} {MACH}\n", argv[0]);
623 		exit(1);
624 	}
625 
626 	objfile = argv[1];
627 	machname = argv[2];
628 
629 	get_ctf_file(objfile);
630 
631 	(void) printf("#include <struct_layout.h>\n");
632 
633 	gen_auxv();
634 	gen_prgregset();
635 	gen_lwpstatus();
636 	gen_pstatus();
637 	gen_prstatus();
638 	gen_psinfo();
639 	gen_prpsinfo();
640 	gen_lwpsinfo();
641 	gen_prcred();
642 	gen_prpriv();
643 	gen_priv_impl_info();
644 	gen_fltset();
645 	gen_siginfo();
646 	gen_sigset();
647 	gen_sigaction();
648 	gen_stack();
649 	gen_sysset();
650 	gen_timestruc();
651 	gen_utsname();
652 	gen_prfdinfo();
653 	gen_prsecflags();
654 	gen_prlwpname();
655 
656 	/*
657 	 * Generate the full arch_layout description
658 	 */
659 	(void) printf(
660 	    "\n\n\n\nstatic const sl_arch_layout_t layout_%s = {\n",
661 	    machname);
662 	(void) printf(fmt, "auxv");
663 	(void) printf(fmt, "fltset");
664 	(void) printf(fmt, "lwpsinfo");
665 	(void) printf(fmt, "lwpstatus");
666 	(void) printf(fmt, "prcred");
667 	(void) printf(fmt, "priv_impl_info");
668 	(void) printf(fmt, "prpriv");
669 	(void) printf(fmt, "psinfo");
670 	(void) printf(fmt, "pstatus");
671 	(void) printf(fmt, "prgregset");
672 	(void) printf(fmt, "prpsinfo");
673 	(void) printf(fmt, "prstatus");
674 	(void) printf(fmt, "sigaction");
675 	(void) printf(fmt, "siginfo");
676 	(void) printf(fmt, "sigset");
677 	(void) printf(fmt, "stack");
678 	(void) printf(fmt, "sysset");
679 	(void) printf(fmt, "timestruc");
680 	(void) printf(fmt, "utsname");
681 	(void) printf(fmt, "prfdinfo");
682 	(void) printf(fmt, "prsecflags");
683 	(void) printf(fmt, "prlwpname");
684 	(void) printf("};\n");
685 
686 	/*
687 	 * A public function, to make the information available
688 	 */
689 	(void) printf("\n\nconst sl_arch_layout_t *\n");
690 	(void) printf("struct_layout_%s(void)\n", machname);
691 	(void) printf("{\n\treturn (&layout_%s);\n}\n", machname);
692 
693 	return (0);
694 }
695 
696 /*
697  * Helper functions using the CTF library to get type info.
698  */
699 
700 static void
701 get_ctf_file(char *fname)
702 {
703 	int ctferr;
704 
705 	objfile = fname;
706 	if ((ctf = ctf_open(objfile, &ctferr)) == NULL) {
707 		errx(1, "Couldn't open object file %s: %s\n", objfile,
708 		    ctf_errmsg(ctferr));
709 	}
710 }
711 
712 static void
713 print_row(int boff, int eltlen, int nelts, int issigned, char *comment)
714 {
715 	(void) printf("\t{ %d,\t%d,\t%d,\t%d },\t\t/* %s */\n",
716 	    boff, eltlen, nelts, issigned, comment);
717 }
718 
719 static void
720 do_start(char *sname, char *tname)
721 {
722 	do_start_name(sname);
723 	do_start_sizeof(tname, NULL);
724 }
725 
726 static void
727 do_start_name(char *sname)
728 {
729 	(void) printf("\n\nstatic const sl_%s_layout_t %s_layout = {\n",
730 	    sname, sname);
731 }
732 
733 static void
734 do_end(void)
735 {
736 	(void) printf("};\n");
737 }
738 
739 static void
740 do_start_sizeof(char *tname, char *rtname)
741 {
742 	char comment[100];
743 	ctf_id_t stype;
744 	int sz;
745 
746 	if (rtname == NULL)
747 		rtname = tname;
748 
749 	if ((stype = ctf_lookup_by_name(ctf, rtname)) == CTF_ERR)
750 		errx(1, "Couldn't find type %s", rtname);
751 	if ((stype = ctf_type_resolve(ctf, stype)) == CTF_ERR)
752 		errx(1, "Couldn't resolve type %s", tname);
753 
754 	if ((sz = (int)ctf_type_size(ctf, stype)) < 0) {
755 		errx(1, "Couldn't get size for type %s", tname);
756 	} else if (sz == 0) {
757 		errx(1, "Invalid type size 0 for %s", tname);
758 	}
759 
760 	(void) snprintf(comment, sizeof (comment), "sizeof (%s)", tname);
761 	print_row(0, sz, 0, 0, comment);
762 }
763 
764 static void
765 do_scalar_field(char *tname, char *fname, int _sign, char *dotfield)
766 {
767 	int rc, off, sz, ftype;
768 
769 	rc = get_field_info(tname, fname, dotfield, &off, &ftype);
770 	if (rc < 0)
771 		errx(1, "Can't get field info for %s->%s", tname, fname);
772 
773 	if ((ftype = ctf_type_resolve(ctf, ftype)) == CTF_ERR)
774 		errx(1, "Couldn't resolve type of %s->%s", tname, fname);
775 
776 	if ((sz = (int)ctf_type_size(ctf, ftype)) < 0) {
777 		errx(1, "Couldn't get size for type ID %d", ftype);
778 	} else if (sz == 0) {
779 		errx(1, "Invalid type size 0 for type ID %d", ftype);
780 	}
781 
782 	print_row(off, sz, 0, _sign, fname);
783 }
784 
785 static void
786 do_array_field(char *tname, char *fname,
787     int _sign, char *dotfield)
788 {
789 	char comment[100];
790 	ctf_arinfo_t ai;
791 	int typekind;
792 	int esz, rc, off, ftype;
793 
794 	rc = get_field_info(tname, fname, dotfield, &off, &ftype);
795 	if (rc < 0)
796 		errx(1, "Can't get field info for %s->%s", tname, fname);
797 
798 	if ((ftype = ctf_type_resolve(ctf, ftype)) == CTF_ERR)
799 		errx(1, "Couldn't resolve type of %s->%s", tname, fname);
800 
801 	typekind = ctf_type_kind(ctf, ftype);
802 	if (typekind != CTF_K_ARRAY)
803 		errx(1, "Wrong type for %s->%s", tname, fname);
804 
805 	rc = ctf_array_info(ctf, ftype, &ai);
806 	if (rc != 0)
807 		errx(1, "Can't get array info for %s->%s\n", tname, fname);
808 	esz = ctf_type_size(ctf, ai.ctr_contents);
809 	if (esz < 0)
810 		errx(1, "Can't get element size for %s->%s\n", tname, fname);
811 
812 	(void) snprintf(comment, sizeof (comment), "%s[]", fname);
813 	print_row(off, esz, ai.ctr_nelems, _sign, comment);
814 }
815 
816 static void
817 do_array_type(char *tname, char *fname,	int _sign)
818 {
819 	ctf_arinfo_t ai;
820 	int stype, typekind;
821 	int esz, rc;
822 
823 	if ((stype = ctf_lookup_by_name(ctf, tname)) == CTF_ERR)
824 		errx(1, "Couldn't find type %s", tname);
825 	if ((stype = ctf_type_resolve(ctf, stype)) == CTF_ERR)
826 		errx(1, "Couldn't resolve type %s", tname);
827 
828 	typekind = ctf_type_kind(ctf, stype);
829 	if (typekind != CTF_K_ARRAY)
830 		errx(1, "Wrong type for %s->%s", tname, fname);
831 
832 	rc = ctf_array_info(ctf, stype, &ai);
833 	if (rc != 0)
834 		errx(1, "Can't get array info for %s->%s\n", tname, fname);
835 	esz = ctf_type_size(ctf, ai.ctr_contents);
836 	if (esz < 0)
837 		errx(1, "Can't get element size for %s->%s\n", tname, fname);
838 
839 	print_row(0, esz, ai.ctr_nelems, _sign, fname);
840 }
841 
842 
843 struct gfinfo {
844 	char *tname;	/* top type name, i.e. the struct */
845 	char *fname;	/* field name */
846 	char *dotname;	/* full field name with dots (optional) */
847 	char *prefix;	/* current field search prefix */
848 	int base_off;
849 	int fld_off;
850 	int fld_type;
851 };
852 
853 static int gfi_iter(const char *fname, ctf_id_t mbrtid,
854 	ulong_t off, void *varg);
855 
856 /*
857  * Lookup field "fname" in type "tname".  If "dotname" is non-NULL,
858  * that's the full field name with dots, i.e. a_un.un_foo, which
859  * we must search for by walking the struct CTF recursively.
860  */
861 static int
862 get_field_info(char *tname, char *fname, char *dotname,
863     int *offp, int *tidp)
864 {
865 	struct gfinfo gfi;
866 	ctf_id_t stype;
867 	int typekind;
868 	int rc;
869 
870 	if ((stype = ctf_lookup_by_name(ctf, tname)) == CTF_ERR)
871 		errx(1, "Couldn't find type %s", tname);
872 	if ((stype = ctf_type_resolve(ctf, stype)) == CTF_ERR)
873 		errx(1, "Couldn't resolve type %s", tname);
874 
875 	/* If fname has a dot, use it as dotname too. */
876 	if (dotname == NULL && strchr(fname, '.') != NULL)
877 		dotname = fname;
878 
879 	gfi.tname = tname;
880 	gfi.fname = fname;
881 	gfi.dotname = dotname;
882 	gfi.prefix = "";
883 	gfi.base_off = 0;
884 	gfi.fld_off = 0;
885 	gfi.fld_type = 0;
886 
887 	typekind = ctf_type_kind(ctf, stype);
888 	switch (typekind) {
889 
890 	case CTF_K_STRUCT:
891 	case CTF_K_UNION:
892 		rc = ctf_member_iter(ctf, stype, gfi_iter, &gfi);
893 		break;
894 
895 	default:
896 		errx(1, "Unexpected top-level type for %s", tname);
897 		break;
898 	}
899 
900 	if (rc < 0)
901 		errx(1, "Error getting info for %s.%s", stype, fname);
902 	if (rc == 0)
903 		errx(1, "Did not find %s.%s", tname, fname);
904 
905 	*offp = gfi.fld_off;
906 	*tidp = gfi.fld_type;
907 
908 	return (0);
909 }
910 
911 /*
912  * Iteration callback for ctf_member_iter
913  * Return <0 on error, 0 to keep looking, >0 for found.
914  *
915  * If no dotname, simple search for fieldname.
916  * If we're asked to search with dotname, we need to do a full
917  * recursive walk of the types under the dotname.
918  */
919 int
920 gfi_iter(const char *fieldname, ctf_id_t mbrtid, ulong_t off, void *varg)
921 {
922 	char namebuf[100];
923 	struct gfinfo *gfi = varg;
924 	char *saveprefix;
925 	int saveoff;
926 	int typekind;
927 	int byteoff;
928 	int len, rc;
929 
930 	byteoff = gfi->base_off + (int)(off >> 3);
931 
932 	/* Easy cases first: no dotname */
933 	if (gfi->dotname == NULL) {
934 		if (strcmp(gfi->fname, fieldname) == 0) {
935 			gfi->fld_off = byteoff;
936 			gfi->fld_type = mbrtid;
937 			return (1);
938 		}
939 		return (0);
940 	}
941 
942 	/* Exact match on the dotname? */
943 	(void) snprintf(namebuf, sizeof (namebuf), "%s%s",
944 	    gfi->prefix, fieldname);
945 	if (strcmp(gfi->dotname, namebuf) == 0) {
946 		gfi->fld_off = byteoff;
947 		gfi->fld_type = mbrtid;
948 		return (1);
949 	}
950 
951 	/*
952 	 * May need to recurse under this field, but
953 	 * only if there's a match through '.'
954 	 */
955 	(void) strlcat(namebuf, ".", sizeof (namebuf));
956 	len = strlen(namebuf);
957 	if (strncmp(gfi->dotname, namebuf, len) != 0)
958 		return (0);
959 
960 	typekind = ctf_type_kind(ctf, mbrtid);
961 	switch (typekind) {
962 	case CTF_K_STRUCT:
963 	case CTF_K_UNION:
964 		break;
965 	default:
966 		return (0);
967 	}
968 
969 	/* Recursively walk members */
970 	saveprefix = gfi->prefix;
971 	saveoff = gfi->base_off;
972 	gfi->prefix = namebuf;
973 	gfi->base_off = byteoff;
974 	rc = ctf_member_iter(ctf, mbrtid, gfi_iter, gfi);
975 	gfi->prefix = saveprefix;
976 	gfi->base_off = saveoff;
977 
978 	return (rc);
979 }
980