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 2009 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 /*
28  * Copyright 2012 DEY Storage Systems, Inc.  All rights reserved.
29  * Copyright 2018 Joyent, Inc.
30  * Copyright 2020 OmniOS Community Edition (OmniOSce) Association.
31  */
32 
33 #ifndef	_STRUCT_LAYOUT_H
34 #define	_STRUCT_LAYOUT_H
35 
36 #include	<conv.h>
37 #include	<_machelf.h>
38 
39 /*
40  * Local include file for elfdump, used to define structure layout
41  * definitions for various system structs.
42  */
43 
44 #ifdef	__cplusplus
45 extern "C" {
46 #endif
47 
48 
49 /*
50  * Solaris defines system structs that elfdump needs to display
51  * data from. We have a variety of hurdles to overcome in doing this:
52  *
53  *	- The size of system types can differ between ELFCLASS32 and
54  *		ELFCLASS64.
55  *	- Stucture layout can differ between architectures, so a given
56  *		field can have a different struct offset than is native
57  *		for the system running elfdump. Depending on the struct
58  *		in question, the layout for one platform may be impossible
59  *		to achieve on another.
60  *	- The byte order of the core object can differ from that
61  *		of the system running elfdump.
62  *
63  * The result is that in the fully general case, each architecture
64  * can have a slightly different definition of these structures.
65  * The usual approach of assigning a pointer of the desired structure
66  * type and then accessing fields through that pointer cannot be used
67  * here. That approach can only be used to access structures with the
68  * native layout of the elfdump host. We want any instance of elfdump
69  * to be able to examine a Solaris object for any supported architecture,
70  * so we need a more flexible approach.
71  *
72  * The solution to this problem lies in the fact that the binary
73  * layout of these public types cannot be changed, except in backward
74  * compatible ways. They are written to core files or published in
75  * other ways such that we can't make changes that would make it
76  * impossible to analyze old files. This means that we can build
77  * table of offsets and sizes for each field of each struct, on
78  * a per-archecture basis. These tables can be used to access the
79  * struct fields directly from the note desc data, and elfdump
80  * on any host can read the data from any other host.
81  *
82  * When reading these tables, it can be very helpful to examine
83  * the struct definition at the same time.
84  */
85 
86 /*
87  * sl_field_t is used to describe a struct field
88  */
89 typedef struct {
90 	ushort_t	slf_offset;	/* Offset from start of struct */
91 	ushort_t	slf_eltlen;	/* Size of datum, in bytes */
92 	ushort_t	slf_nelts;	/* 0 for scalar, # of els for array */
93 	uchar_t		slf_sign;	/* True (1) if signed quantity */
94 } sl_field_t;
95 
96 /*
97  * This type is used to extract and manipulate data described by
98  * sl_field_t. We rely on the C guarantee that all the fields in
99  * a union have offset 0.
100  */
101 typedef union {
102 	char		sld_i8;
103 	uchar_t		sld_ui8;
104 	short		sld_i16;
105 	ushort_t	sld_ui16;
106 	int32_t		sld_i32;
107 	uint32_t	sld_ui32;
108 	int64_t		sld_i64;
109 	uint64_t	sld_ui64;
110 } sl_data_t;
111 
112 /*
113  * Buffer large enough to format any integral value in a field
114  */
115 typedef char sl_fmtbuf_t[CONV_INV_BUFSIZE * 2];
116 
117 /*
118  * Types of formatting done by fmt_num()
119  */
120 typedef enum {
121 	SL_FMT_NUM_DEC = 0,	/* Decimal integer */
122 	SL_FMT_NUM_HEX = 1,	/* Hex integer, with natural width */
123 	SL_FMT_NUM_ZHEX = 2,	/* Hex integer, fixed width with zero fill  */
124 } sl_fmt_num_t;
125 
126 
127 
128 
129 /*
130  * Layout description of auxv_t, from <sys/auxv.h>.
131  */
132 typedef struct {
133 	sl_field_t		sizeof_struct;
134 	sl_field_t		a_type;
135 	sl_field_t		a_val;
136 	sl_field_t		a_ptr;
137 	sl_field_t		a_fcn;
138 } sl_auxv_layout_t;
139 
140 /*
141  * Layout description of prgregset_t, an architecture specific
142  * array of general register c values
143  */
144 typedef struct {
145 	sl_field_t		sizeof_struct;
146 	sl_field_t		elt0;
147 } sl_prgregset_layout_t;
148 
149 /*
150  * Layout description of lwpstatus_t, from <sys/procfs.h>.
151  */
152 typedef struct {
153 	sl_field_t		sizeof_struct;
154 	sl_field_t		pr_flags;
155 	sl_field_t		pr_lwpid;
156 	sl_field_t		pr_why;
157 	sl_field_t		pr_what;
158 	sl_field_t		pr_cursig;
159 	sl_field_t		pr_info;
160 	sl_field_t		pr_lwppend;
161 	sl_field_t		pr_lwphold;
162 	sl_field_t		pr_action;
163 	sl_field_t		pr_altstack;
164 	sl_field_t		pr_oldcontext;
165 	sl_field_t		pr_syscall;
166 	sl_field_t		pr_nsysarg;
167 	sl_field_t		pr_errno;
168 	sl_field_t		pr_sysarg;
169 	sl_field_t		pr_rval1;
170 	sl_field_t		pr_rval2;
171 	sl_field_t		pr_clname;
172 	sl_field_t		pr_tstamp;
173 	sl_field_t		pr_utime;
174 	sl_field_t		pr_stime;
175 	sl_field_t		pr_errpriv;
176 	sl_field_t		pr_ustack;
177 	sl_field_t		pr_instr;
178 	sl_field_t		pr_reg;
179 	sl_field_t		pr_fpreg;
180 } sl_lwpstatus_layout_t;
181 
182 /*
183  * Layout description of pstatus_t, from <sys/procfs.h>.
184  */
185 typedef struct {
186 	sl_field_t		sizeof_struct;
187 	sl_field_t		pr_flags;
188 	sl_field_t		pr_nlwp;
189 	sl_field_t		pr_pid;
190 	sl_field_t		pr_ppid;
191 	sl_field_t		pr_pgid;
192 	sl_field_t		pr_sid;
193 	sl_field_t		pr_aslwpid;
194 	sl_field_t		pr_agentid;
195 	sl_field_t		pr_sigpend;
196 	sl_field_t		pr_brkbase;
197 	sl_field_t		pr_brksize;
198 	sl_field_t		pr_stkbase;
199 	sl_field_t		pr_stksize;
200 	sl_field_t		pr_utime;
201 	sl_field_t		pr_stime;
202 	sl_field_t		pr_cutime;
203 	sl_field_t		pr_cstime;
204 	sl_field_t		pr_sigtrace;
205 	sl_field_t		pr_flttrace;
206 	sl_field_t		pr_sysentry;
207 	sl_field_t		pr_sysexit;
208 	sl_field_t		pr_dmodel;
209 	sl_field_t		pr_taskid;
210 	sl_field_t		pr_projid;
211 	sl_field_t		pr_nzomb;
212 	sl_field_t		pr_zoneid;
213 	sl_field_t		pr_lwp;
214 } sl_pstatus_layout_t;
215 
216 /*
217  * Layout description of prstatus_t, from <sys/old_procfs.h>.
218  */
219 typedef struct {
220 	sl_field_t		sizeof_struct;
221 	sl_field_t		pr_flags;
222 	sl_field_t		pr_why;
223 	sl_field_t		pr_what;
224 	sl_field_t		pr_info;
225 	sl_field_t		pr_cursig;
226 	sl_field_t		pr_nlwp;
227 	sl_field_t		pr_sigpend;
228 	sl_field_t		pr_sighold;
229 	sl_field_t		pr_altstack;
230 	sl_field_t		pr_action;
231 	sl_field_t		pr_pid;
232 	sl_field_t		pr_ppid;
233 	sl_field_t		pr_pgrp;
234 	sl_field_t		pr_sid;
235 	sl_field_t		pr_utime;
236 	sl_field_t		pr_stime;
237 	sl_field_t		pr_cutime;
238 	sl_field_t		pr_cstime;
239 	sl_field_t		pr_clname;
240 	sl_field_t		pr_syscall;
241 	sl_field_t		pr_nsysarg;
242 	sl_field_t		pr_sysarg;
243 	sl_field_t		pr_who;
244 	sl_field_t		pr_lwppend;
245 	sl_field_t		pr_oldcontext;
246 	sl_field_t		pr_brkbase;
247 	sl_field_t		pr_brksize;
248 	sl_field_t		pr_stkbase;
249 	sl_field_t		pr_stksize;
250 	sl_field_t		pr_processor;
251 	sl_field_t		pr_bind;
252 	sl_field_t		pr_instr;
253 	sl_field_t		pr_reg;
254 } sl_prstatus_layout_t;
255 
256 /*
257  * Layout description of psinfo_t, from <sys/procfs.h>.
258  */
259 typedef struct {
260 	sl_field_t		sizeof_struct;
261 	sl_field_t		pr_flag;
262 	sl_field_t		pr_nlwp;
263 	sl_field_t		pr_pid;
264 	sl_field_t		pr_ppid;
265 	sl_field_t		pr_pgid;
266 	sl_field_t		pr_sid;
267 	sl_field_t		pr_uid;
268 	sl_field_t		pr_euid;
269 	sl_field_t		pr_gid;
270 	sl_field_t		pr_egid;
271 	sl_field_t		pr_addr;
272 	sl_field_t		pr_size;
273 	sl_field_t		pr_rssize;
274 	sl_field_t		pr_ttydev;
275 	sl_field_t		pr_pctcpu;
276 	sl_field_t		pr_pctmem;
277 	sl_field_t		pr_start;
278 	sl_field_t		pr_time;
279 	sl_field_t		pr_ctime;
280 	sl_field_t		pr_fname;
281 	sl_field_t		pr_psargs;
282 	sl_field_t		pr_wstat;
283 	sl_field_t		pr_argc;
284 	sl_field_t		pr_argv;
285 	sl_field_t		pr_envp;
286 	sl_field_t		pr_dmodel;
287 	sl_field_t		pr_taskid;
288 	sl_field_t		pr_projid;
289 	sl_field_t		pr_nzomb;
290 	sl_field_t		pr_poolid;
291 	sl_field_t		pr_zoneid;
292 	sl_field_t		pr_contract;
293 	sl_field_t		pr_lwp;
294 } sl_psinfo_layout_t;
295 
296 /*
297  * Layout description of prpsinfo_t, from <sys/old_procfs.h>.
298  */
299 typedef struct {
300 	sl_field_t		sizeof_struct;
301 	sl_field_t		pr_state;
302 	sl_field_t		pr_sname;
303 	sl_field_t		pr_zomb;
304 	sl_field_t		pr_nice;
305 	sl_field_t		pr_flag;
306 	sl_field_t		pr_uid;
307 	sl_field_t		pr_gid;
308 	sl_field_t		pr_pid;
309 	sl_field_t		pr_ppid;
310 	sl_field_t		pr_pgrp;
311 	sl_field_t		pr_sid;
312 	sl_field_t		pr_addr;
313 	sl_field_t		pr_size;
314 	sl_field_t		pr_rssize;
315 	sl_field_t		pr_wchan;
316 	sl_field_t		pr_start;
317 	sl_field_t		pr_time;
318 	sl_field_t		pr_pri;
319 	sl_field_t		pr_oldpri;
320 	sl_field_t		pr_cpu;
321 	sl_field_t		pr_ottydev;
322 	sl_field_t		pr_lttydev;
323 	sl_field_t		pr_clname;
324 	sl_field_t		pr_fname;
325 	sl_field_t		pr_psargs;
326 	sl_field_t		pr_syscall;
327 	sl_field_t		pr_ctime;
328 	sl_field_t		pr_bysize;
329 	sl_field_t		pr_byrssize;
330 	sl_field_t		pr_argc;
331 	sl_field_t		pr_argv;
332 	sl_field_t		pr_envp;
333 	sl_field_t		pr_wstat;
334 	sl_field_t		pr_pctcpu;
335 	sl_field_t		pr_pctmem;
336 	sl_field_t		pr_euid;
337 	sl_field_t		pr_egid;
338 	sl_field_t		pr_aslwpid;
339 	sl_field_t		pr_dmodel;
340 } sl_prpsinfo_layout_t;
341 
342 /*
343  * Layout description of lwpsinfo_t, from <sys/procfs.h>.
344  */
345 typedef struct {
346 	sl_field_t		sizeof_struct;
347 	sl_field_t		pr_flag;
348 	sl_field_t		pr_lwpid;
349 	sl_field_t		pr_addr;
350 	sl_field_t		pr_wchan;
351 	sl_field_t		pr_stype;
352 	sl_field_t		pr_state;
353 	sl_field_t		pr_sname;
354 	sl_field_t		pr_nice;
355 	sl_field_t		pr_syscall;
356 	sl_field_t		pr_oldpri;
357 	sl_field_t		pr_cpu;
358 	sl_field_t		pr_pri;
359 	sl_field_t		pr_pctcpu;
360 	sl_field_t		pr_start;
361 	sl_field_t		pr_time;
362 	sl_field_t		pr_clname;
363 	sl_field_t		pr_name;
364 	sl_field_t		pr_onpro;
365 	sl_field_t		pr_bindpro;
366 	sl_field_t		pr_bindpset;
367 	sl_field_t		pr_lgrp;
368 } sl_lwpsinfo_layout_t;
369 
370 /*
371  * Layout description of prcred_t, from <sys/procfs.h>.
372  */
373 typedef struct {
374 	sl_field_t		sizeof_struct;
375 	sl_field_t		pr_euid;
376 	sl_field_t		pr_ruid;
377 	sl_field_t		pr_suid;
378 	sl_field_t		pr_egid;
379 	sl_field_t		pr_rgid;
380 	sl_field_t		pr_sgid;
381 	sl_field_t		pr_ngroups;
382 	sl_field_t		pr_groups;
383 } sl_prcred_layout_t;
384 
385 /*
386  * Layout description of prpriv_t, from <sys/procfs.h>.
387  */
388 typedef struct {
389 	sl_field_t		sizeof_struct;
390 	sl_field_t		pr_nsets;
391 	sl_field_t		pr_setsize;
392 	sl_field_t		pr_infosize;
393 	sl_field_t		pr_sets;
394 } sl_prpriv_layout_t;
395 
396 /*
397  * Layout description of priv_impl_info_t, from <sys/priv.h>.
398  */
399 typedef struct {
400 	sl_field_t		sizeof_struct;
401 	sl_field_t		priv_headersize;
402 	sl_field_t		priv_flags;
403 	sl_field_t		priv_nsets;
404 	sl_field_t		priv_setsize;
405 	sl_field_t		priv_max;
406 	sl_field_t		priv_infosize;
407 	sl_field_t		priv_globalinfosize;
408 } sl_priv_impl_info_layout_t;
409 
410 /*
411  * Layout description of fltset_t, from <sys/fault.h>.
412  */
413 typedef struct {
414 	sl_field_t		sizeof_struct;
415 	sl_field_t		word;
416 } sl_fltset_layout_t;
417 
418 /*
419  * Layout description of siginfo_t, from <sys/siginfo.h>.
420  *
421  * siginfo_t is unusual, in that it contains a large union
422  * full of private fields. There are macros defined to give
423  * access to these fields via the names documented in the
424  * siginfo manpage. We stick to the documented names
425  * rather than try to unravel the undocumented blob. Hence,
426  * the layout description below is a "logical" view of siginfo_t.
427  * The fields below are not necessarily in the same order as
428  * they appear in siginfo_t, nor are they everything that is in
429  * that struct. They may also overlap each other, if they are
430  * contained within of the union.
431  *
432  * The f_ prefixes are used to prevent our field names from
433  * clashing with the macros defined in siginfo.h.
434  */
435 typedef struct {
436 	sl_field_t		sizeof_struct;
437 	sl_field_t		f_si_signo;
438 	sl_field_t		f_si_errno;
439 	sl_field_t		f_si_code;
440 	sl_field_t		f_si_value_int;
441 	sl_field_t		f_si_value_ptr;
442 	sl_field_t		f_si_pid;
443 	sl_field_t		f_si_uid;
444 	sl_field_t		f_si_ctid;
445 	sl_field_t		f_si_zoneid;
446 	sl_field_t		f_si_entity;
447 	sl_field_t		f_si_addr;
448 	sl_field_t		f_si_status;
449 	sl_field_t		f_si_band;
450 } sl_siginfo_layout_t;
451 
452 /*
453  * Layout description of sigset_t, from <sys/signal.h>.
454  */
455 typedef struct {
456 	sl_field_t		sizeof_struct;
457 	sl_field_t		sigbits;
458 } sl_sigset_layout_t;
459 
460 /*
461  * Layout description of struct sigaction, from <sys/signal.h>.
462  */
463 typedef struct {
464 	sl_field_t		sizeof_struct;
465 	sl_field_t		sa_flags;
466 	sl_field_t		sa_hand;
467 	sl_field_t		sa_sigact;
468 	sl_field_t		sa_mask;
469 } sl_sigaction_layout_t;
470 
471 /*
472  * Layout description of stack_t, from <sys/signal.h>.
473  */
474 typedef struct {
475 	sl_field_t		sizeof_struct;
476 	sl_field_t		ss_sp;
477 	sl_field_t		ss_size;
478 	sl_field_t		ss_flags;
479 } sl_stack_layout_t;
480 
481 /*
482  * Layout description of sysset_t, from <sys/syscall.h>.
483  */
484 typedef struct {
485 	sl_field_t		sizeof_struct;
486 	sl_field_t		word;
487 } sl_sysset_layout_t;
488 
489 /*
490  * Layout description of timestruc_t, from <sys/time_impl.h>.
491  */
492 typedef struct {
493 	sl_field_t		sizeof_struct;
494 	sl_field_t		tv_sec;
495 	sl_field_t		tv_nsec;
496 } sl_timestruc_layout_t;
497 
498 /*
499  * Layout description of struct utsname, from <sys/utsname.h>.
500  */
501 typedef struct {
502 	sl_field_t		sizeof_struct;
503 	sl_field_t		sysname;
504 	sl_field_t		nodename;
505 	sl_field_t		release;
506 	sl_field_t		version;
507 	sl_field_t		machine;
508 } sl_utsname_layout_t;
509 
510 /*
511  * Layout description of prfdinfo_core_t, from <sys/procfs.h>.
512  */
513 typedef struct {
514 	sl_field_t		sizeof_struct;
515 	sl_field_t		pr_fd;
516 	sl_field_t		pr_mode;
517 	sl_field_t		pr_uid;
518 	sl_field_t		pr_gid;
519 	sl_field_t		pr_major;
520 	sl_field_t		pr_minor;
521 	sl_field_t		pr_rmajor;
522 	sl_field_t		pr_rminor;
523 	sl_field_t		pr_ino;
524 	sl_field_t		pr_offset;
525 	sl_field_t		pr_size;
526 	sl_field_t		pr_fileflags;
527 	sl_field_t		pr_fdflags;
528 	sl_field_t		pr_path;
529 } sl_prfdinfo_layout_t;
530 
531 typedef struct {
532 	sl_field_t		sizeof_struct;
533 	sl_field_t		pr_version;
534 	sl_field_t		pr_effective;
535 	sl_field_t		pr_inherit;
536 	sl_field_t		pr_lower;
537 	sl_field_t		pr_upper;
538 } sl_prsecflags_layout_t;
539 
540 typedef struct {
541 	sl_field_t		sizeof_struct;
542 	sl_field_t		pr_lwpid;
543 	sl_field_t		pr_lwpname;
544 } sl_prlwpname_layout_t;
545 
546 typedef struct {
547 	sl_field_t		sizeof_struct;
548 	sl_field_t		pru_version;
549 	sl_field_t		pru_flags;
550 	sl_field_t		pru_data;
551 } sl_prupanic_layout_t;
552 
553 /*
554  * This type collects all of the layout definitions for
555  * a given architecture.
556  */
557 typedef struct {
558 	const sl_auxv_layout_t		*auxv;		/* auxv_t */
559 	const sl_fltset_layout_t	*fltset;	/* fltset_t */
560 	const sl_lwpsinfo_layout_t	*lwpsinfo;	/* lwpsinfo_t */
561 	const sl_lwpstatus_layout_t	*lwpstatus;	/* lwpstatus_t */
562 	const sl_prcred_layout_t	*prcred;	/* prcred_t */
563 	const sl_priv_impl_info_layout_t *priv_impl_info; /* priv_impl_info_t */
564 	const sl_prpriv_layout_t	*prpriv;	/* prpriv_t */
565 	const sl_psinfo_layout_t	*psinfo;	/* psinfo_t */
566 	const sl_pstatus_layout_t	*pstatus;	/* pstatus_t */
567 	const sl_prgregset_layout_t	*prgregset;	/* prgregset_t */
568 	const sl_prpsinfo_layout_t	*prpsinfo;	/* prpsinfo_t */
569 	const sl_prstatus_layout_t	*prstatus;	/* prstatus_t */
570 	const sl_sigaction_layout_t	*sigaction;	/* struct sigaction */
571 	const sl_siginfo_layout_t	*siginfo;	/* siginfo_t */
572 	const sl_sigset_layout_t	*sigset;	/* sigset_t */
573 	const sl_stack_layout_t		*stack;		/* stack_t */
574 	const sl_sysset_layout_t	*sysset;	/* sysset_t */
575 	const sl_timestruc_layout_t	*timestruc;	/* timestruc_t */
576 	const sl_utsname_layout_t	*utsname;	/* struct utsname */
577 	const sl_prfdinfo_layout_t	*prfdinfo;	/* prdinfo_t */
578 	const sl_prsecflags_layout_t	*prsecflags;	/* prsecflags_t */
579 	const sl_prlwpname_layout_t	*prlwpname;	/* prlwpname_t */
580 	const sl_prupanic_layout_t	*prupanic;	/* prupanic_t */
581 } sl_arch_layout_t;
582 
583 
584 
585 extern	void		sl_extract_num_field(const char *data, int do_swap,
586 			    const sl_field_t *fdesc, sl_data_t *field_data);
587 extern	Word		sl_extract_as_word(const char *data, int do_swap,
588 			    const sl_field_t *fdesc);
589 extern	Lword		sl_extract_as_lword(const char *data, int do_swap,
590 			    const sl_field_t *fdesc);
591 extern	Sword		sl_extract_as_sword(const char *data, int do_swap,
592 			    const sl_field_t *fdesc);
593 extern	const char	*sl_fmt_num(const char *data, int do_swap,
594 			    const sl_field_t *fdesc, sl_fmt_num_t fmt_type,
595 			    sl_fmtbuf_t buf);
596 
597 
598 extern	const sl_arch_layout_t	*sl_mach(Half);
599 extern	const sl_arch_layout_t	*struct_layout_i386(void);
600 extern	const sl_arch_layout_t	*struct_layout_amd64(void);
601 extern	const sl_arch_layout_t	*struct_layout_sparc(void);
602 extern	const sl_arch_layout_t	*struct_layout_sparcv9(void);
603 
604 
605 
606 #ifdef	__cplusplus
607 }
608 #endif
609 
610 #endif	/* _STRUCT_LAYOUT_H */
611