/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. * * Copyright 2015 Nexenta Systems, Inc. All rights reserved. * Copyright 2018 Joyent, Inc. * Copyright 2020 OmniOS Community Edition (OmniOSce) Association. */ /* * This program is used to generate the contents of the * struct_layout_XXX.c files that contain per-architecture * structure layout information. * * Although not part of elfdump, it is built by the makefile * along with it. * To use it: * * 1) Run it, capturing the output in a file. * 2) If this is a replacement for an existing file, * diff the new and old copies to ensure only * the changes you expected are present. * 3) Put the new file in the common directory under the name * struct_layout_XXX.c, where XXX is the name of * the architecture (i386, amd64, sparc, sparcv9, etc). * 2) Add any necessary header and copyright comments. * 3) If this is a new architecture: * - Add an extern statement for struct_layout_XXX() * to struct_layout.h * - Add a case for it to the function sl_struct_layout() * in struct_layout.c. */ #include #include #include #include #include #include #include /* * This extracts CTF information from a temporary object file. * * START and END bracket a struct layout definition. They issue * the typedef boilerplate, and the standard first element (sizeof) * which captures the overall size of the structure. * * SCALAR_FIELD is for scalar struct fields * * ARRAY_FIELD is for array struct fields * * ARRAY_TYPE is for plain (non-struct) array types */ #define START(_name, _type) \ do_start(#_name, #_type) #define END (void) \ do_end() #define SCALAR_FIELD(_type, _field, _sign) \ do_scalar_field(#_type, #_field, _sign, NULL) #define SCALAR_FIELD4(_type, _field, _sign, _rtype) \ do_scalar_field(#_type, #_field, _sign, _rtype) #define ARRAY_FIELD(_type, _field, _sign) \ do_array_field(#_type, #_field, _sign, NULL) #define ARRAY_TYPE(_type, _sign) \ do_array_type(#_type, "elt0", _sign) static void do_start(char *_name, char *_type); static void do_end(void); static void do_start_name(char *name); static void do_start_sizeof(char *_type, char *realtype); static void do_scalar_field(char *_type, char *_field, int _sign, char *dotfield); static void do_array_field(char *_type, char *_field, int _sign, char *dotfield); static void do_array_type(char *_type, char *_field, int _sign); static void get_ctf_file(char *fname); static int get_field_info(char *tname, char *fname, char *dotname, int *offp, int *sizep); static ctf_file_t *ctf; static char *objfile; static char *machname; /* auxv_t, */ static void gen_auxv(void) { START(auxv, auxv_t); SCALAR_FIELD(auxv_t, a_type, 1); SCALAR_FIELD(auxv_t, a_un.a_val, 1); SCALAR_FIELD(auxv_t, a_un.a_ptr, 0); SCALAR_FIELD(auxv_t, a_un.a_fcn, 0); END; } /* prgregset_t, */ static void gen_prgregset(void) { START(prgregset, prgregset_t); ARRAY_TYPE(prgregset_t, 0); END; } /* lwpstatus_t, */ static void gen_lwpstatus(void) { START(lwpstatus, lwpstatus_t); SCALAR_FIELD(lwpstatus_t, pr_flags, 0); SCALAR_FIELD(lwpstatus_t, pr_lwpid, 0); SCALAR_FIELD(lwpstatus_t, pr_why, 0); SCALAR_FIELD(lwpstatus_t, pr_what, 0); SCALAR_FIELD(lwpstatus_t, pr_cursig, 0); SCALAR_FIELD(lwpstatus_t, pr_info, 0); SCALAR_FIELD(lwpstatus_t, pr_lwppend, 0); SCALAR_FIELD(lwpstatus_t, pr_lwphold, 0); SCALAR_FIELD(lwpstatus_t, pr_action, 0); SCALAR_FIELD(lwpstatus_t, pr_altstack, 0); SCALAR_FIELD(lwpstatus_t, pr_oldcontext, 0); SCALAR_FIELD(lwpstatus_t, pr_syscall, 0); SCALAR_FIELD(lwpstatus_t, pr_nsysarg, 0); SCALAR_FIELD(lwpstatus_t, pr_errno, 0); ARRAY_FIELD(lwpstatus_t, pr_sysarg, 0); SCALAR_FIELD(lwpstatus_t, pr_rval1, 0); SCALAR_FIELD(lwpstatus_t, pr_rval2, 0); ARRAY_FIELD(lwpstatus_t, pr_clname, 0); SCALAR_FIELD(lwpstatus_t, pr_tstamp, 0); SCALAR_FIELD(lwpstatus_t, pr_utime, 0); SCALAR_FIELD(lwpstatus_t, pr_stime, 0); SCALAR_FIELD(lwpstatus_t, pr_errpriv, 0); SCALAR_FIELD(lwpstatus_t, pr_ustack, 0); SCALAR_FIELD(lwpstatus_t, pr_instr, 0); SCALAR_FIELD(lwpstatus_t, pr_reg, 0); SCALAR_FIELD(lwpstatus_t, pr_fpreg, 0); END; } /* pstatus_t, */ static void gen_pstatus(void) { START(pstatus, pstatus_t); SCALAR_FIELD(pstatus_t, pr_flags, 1); SCALAR_FIELD(pstatus_t, pr_nlwp, 1); SCALAR_FIELD(pstatus_t, pr_pid, 0); SCALAR_FIELD(pstatus_t, pr_ppid, 0); SCALAR_FIELD(pstatus_t, pr_pgid, 0); SCALAR_FIELD(pstatus_t, pr_sid, 0); SCALAR_FIELD(pstatus_t, pr_aslwpid, 1); SCALAR_FIELD(pstatus_t, pr_agentid, 1); SCALAR_FIELD(pstatus_t, pr_sigpend, 0); SCALAR_FIELD(pstatus_t, pr_brkbase, 0); SCALAR_FIELD(pstatus_t, pr_brksize, 0); SCALAR_FIELD(pstatus_t, pr_stkbase, 0); SCALAR_FIELD(pstatus_t, pr_stksize, 0); SCALAR_FIELD(pstatus_t, pr_utime, 0); SCALAR_FIELD(pstatus_t, pr_stime, 0); SCALAR_FIELD(pstatus_t, pr_cutime, 0); SCALAR_FIELD(pstatus_t, pr_cstime, 0); SCALAR_FIELD(pstatus_t, pr_sigtrace, 0); SCALAR_FIELD(pstatus_t, pr_flttrace, 0); SCALAR_FIELD(pstatus_t, pr_sysentry, 0); SCALAR_FIELD(pstatus_t, pr_sysexit, 0); SCALAR_FIELD(pstatus_t, pr_dmodel, 0); SCALAR_FIELD(pstatus_t, pr_taskid, 1); SCALAR_FIELD(pstatus_t, pr_projid, 1); SCALAR_FIELD(pstatus_t, pr_nzomb, 1); SCALAR_FIELD(pstatus_t, pr_zoneid, 1); SCALAR_FIELD(pstatus_t, pr_lwp, 0); END; } /* prstatus_t, */ static void gen_prstatus(void) { START(prstatus, prstatus_t); SCALAR_FIELD(prstatus_t, pr_flags, 1); SCALAR_FIELD(prstatus_t, pr_why, 1); SCALAR_FIELD(prstatus_t, pr_what, 1); SCALAR_FIELD(prstatus_t, pr_info, 0); SCALAR_FIELD(prstatus_t, pr_cursig, 1); SCALAR_FIELD(prstatus_t, pr_nlwp, 0); SCALAR_FIELD(prstatus_t, pr_sigpend, 0); SCALAR_FIELD(prstatus_t, pr_sighold, 0); SCALAR_FIELD(prstatus_t, pr_altstack, 0); SCALAR_FIELD(prstatus_t, pr_action, 0); SCALAR_FIELD(prstatus_t, pr_pid, 0); SCALAR_FIELD(prstatus_t, pr_ppid, 0); SCALAR_FIELD(prstatus_t, pr_pgrp, 0); SCALAR_FIELD(prstatus_t, pr_sid, 0); SCALAR_FIELD(prstatus_t, pr_utime, 0); SCALAR_FIELD(prstatus_t, pr_stime, 0); SCALAR_FIELD(prstatus_t, pr_cutime, 0); SCALAR_FIELD(prstatus_t, pr_cstime, 0); ARRAY_FIELD(prstatus_t, pr_clname, 0); SCALAR_FIELD(prstatus_t, pr_syscall, 1); SCALAR_FIELD(prstatus_t, pr_nsysarg, 1); ARRAY_FIELD(prstatus_t, pr_sysarg, 1); SCALAR_FIELD(prstatus_t, pr_who, 0); SCALAR_FIELD(prstatus_t, pr_lwppend, 0); SCALAR_FIELD(prstatus_t, pr_oldcontext, 0); SCALAR_FIELD(prstatus_t, pr_brkbase, 0); SCALAR_FIELD(prstatus_t, pr_brksize, 0); SCALAR_FIELD(prstatus_t, pr_stkbase, 0); SCALAR_FIELD(prstatus_t, pr_stksize, 0); SCALAR_FIELD(prstatus_t, pr_processor, 1); SCALAR_FIELD(prstatus_t, pr_bind, 1); SCALAR_FIELD(prstatus_t, pr_instr, 1); SCALAR_FIELD(prstatus_t, pr_reg, 0); END; } /* psinfo_t, */ static void gen_psinfo(void) { START(psinfo, psinfo_t); SCALAR_FIELD(psinfo_t, pr_flag, 1); SCALAR_FIELD(psinfo_t, pr_nlwp, 1); SCALAR_FIELD(psinfo_t, pr_pid, 0); SCALAR_FIELD(psinfo_t, pr_ppid, 0); SCALAR_FIELD(psinfo_t, pr_pgid, 0); SCALAR_FIELD(psinfo_t, pr_sid, 0); SCALAR_FIELD(psinfo_t, pr_uid, 0); SCALAR_FIELD(psinfo_t, pr_euid, 0); SCALAR_FIELD(psinfo_t, pr_gid, 0); SCALAR_FIELD(psinfo_t, pr_egid, 0); SCALAR_FIELD(psinfo_t, pr_addr, 0); SCALAR_FIELD(psinfo_t, pr_size, 0); SCALAR_FIELD(psinfo_t, pr_rssize, 0); SCALAR_FIELD(psinfo_t, pr_ttydev, 0); SCALAR_FIELD(psinfo_t, pr_pctcpu, 0); SCALAR_FIELD(psinfo_t, pr_pctmem, 0); SCALAR_FIELD(psinfo_t, pr_start, 0); SCALAR_FIELD(psinfo_t, pr_time, 0); SCALAR_FIELD(psinfo_t, pr_ctime, 0); ARRAY_FIELD(psinfo_t, pr_fname, 0); ARRAY_FIELD(psinfo_t, pr_psargs, 0); SCALAR_FIELD(psinfo_t, pr_wstat, 1); SCALAR_FIELD(psinfo_t, pr_argc, 1); SCALAR_FIELD(psinfo_t, pr_argv, 0); SCALAR_FIELD(psinfo_t, pr_envp, 0); SCALAR_FIELD(psinfo_t, pr_dmodel, 0); SCALAR_FIELD(psinfo_t, pr_taskid, 0); SCALAR_FIELD(psinfo_t, pr_projid, 0); SCALAR_FIELD(psinfo_t, pr_nzomb, 1); SCALAR_FIELD(psinfo_t, pr_poolid, 0); SCALAR_FIELD(psinfo_t, pr_zoneid, 0); SCALAR_FIELD(psinfo_t, pr_contract, 0); SCALAR_FIELD(psinfo_t, pr_lwp, 0); END; } /* prpsinfo_t, */ static void gen_prpsinfo(void) { START(prpsinfo, prpsinfo_t); SCALAR_FIELD(prpsinfo_t, pr_state, 0); SCALAR_FIELD(prpsinfo_t, pr_sname, 0); SCALAR_FIELD(prpsinfo_t, pr_zomb, 0); SCALAR_FIELD(prpsinfo_t, pr_nice, 0); SCALAR_FIELD(prpsinfo_t, pr_flag, 0); SCALAR_FIELD(prpsinfo_t, pr_uid, 0); SCALAR_FIELD(prpsinfo_t, pr_gid, 0); SCALAR_FIELD(prpsinfo_t, pr_pid, 0); SCALAR_FIELD(prpsinfo_t, pr_ppid, 0); SCALAR_FIELD(prpsinfo_t, pr_pgrp, 0); SCALAR_FIELD(prpsinfo_t, pr_sid, 0); SCALAR_FIELD(prpsinfo_t, pr_addr, 0); SCALAR_FIELD(prpsinfo_t, pr_size, 0); SCALAR_FIELD(prpsinfo_t, pr_rssize, 0); SCALAR_FIELD(prpsinfo_t, pr_wchan, 0); SCALAR_FIELD(prpsinfo_t, pr_start, 0); SCALAR_FIELD(prpsinfo_t, pr_time, 0); SCALAR_FIELD(prpsinfo_t, pr_pri, 1); SCALAR_FIELD(prpsinfo_t, pr_oldpri, 0); SCALAR_FIELD(prpsinfo_t, pr_cpu, 0); SCALAR_FIELD(prpsinfo_t, pr_ottydev, 0); SCALAR_FIELD(prpsinfo_t, pr_lttydev, 0); ARRAY_FIELD(prpsinfo_t, pr_clname, 0); ARRAY_FIELD(prpsinfo_t, pr_fname, 0); ARRAY_FIELD(prpsinfo_t, pr_psargs, 0); SCALAR_FIELD(prpsinfo_t, pr_syscall, 1); SCALAR_FIELD(prpsinfo_t, pr_ctime, 0); SCALAR_FIELD(prpsinfo_t, pr_bysize, 0); SCALAR_FIELD(prpsinfo_t, pr_byrssize, 0); SCALAR_FIELD(prpsinfo_t, pr_argc, 1); SCALAR_FIELD(prpsinfo_t, pr_argv, 0); SCALAR_FIELD(prpsinfo_t, pr_envp, 0); SCALAR_FIELD(prpsinfo_t, pr_wstat, 1); SCALAR_FIELD(prpsinfo_t, pr_pctcpu, 0); SCALAR_FIELD(prpsinfo_t, pr_pctmem, 0); SCALAR_FIELD(prpsinfo_t, pr_euid, 0); SCALAR_FIELD(prpsinfo_t, pr_egid, 0); SCALAR_FIELD(prpsinfo_t, pr_aslwpid, 0); SCALAR_FIELD(prpsinfo_t, pr_dmodel, 0); END; } /* lwpsinfo_t, */ static void gen_lwpsinfo(void) { START(lwpsinfo, lwpsinfo_t); SCALAR_FIELD(lwpsinfo_t, pr_flag, 1); SCALAR_FIELD(lwpsinfo_t, pr_lwpid, 0); SCALAR_FIELD(lwpsinfo_t, pr_addr, 0); SCALAR_FIELD(lwpsinfo_t, pr_wchan, 0); SCALAR_FIELD(lwpsinfo_t, pr_stype, 0); SCALAR_FIELD(lwpsinfo_t, pr_state, 0); SCALAR_FIELD(lwpsinfo_t, pr_sname, 0); SCALAR_FIELD(lwpsinfo_t, pr_nice, 0); SCALAR_FIELD(lwpsinfo_t, pr_syscall, 0); SCALAR_FIELD(lwpsinfo_t, pr_oldpri, 0); SCALAR_FIELD(lwpsinfo_t, pr_cpu, 0); SCALAR_FIELD(lwpsinfo_t, pr_pri, 1); SCALAR_FIELD(lwpsinfo_t, pr_pctcpu, 0); SCALAR_FIELD(lwpsinfo_t, pr_start, 0); SCALAR_FIELD(lwpsinfo_t, pr_time, 0); ARRAY_FIELD(lwpsinfo_t, pr_clname, 0); ARRAY_FIELD(lwpsinfo_t, pr_name, 0); SCALAR_FIELD(lwpsinfo_t, pr_onpro, 1); SCALAR_FIELD(lwpsinfo_t, pr_bindpro, 1); SCALAR_FIELD(lwpsinfo_t, pr_bindpset, 1); SCALAR_FIELD(lwpsinfo_t, pr_lgrp, 1); END; } /* prcred_t, */ static void gen_prcred(void) { START(prcred, prcred_t); SCALAR_FIELD(prcred_t, pr_euid, 0); SCALAR_FIELD(prcred_t, pr_ruid, 0); SCALAR_FIELD(prcred_t, pr_suid, 0); SCALAR_FIELD(prcred_t, pr_egid, 0); SCALAR_FIELD(prcred_t, pr_rgid, 0); SCALAR_FIELD(prcred_t, pr_sgid, 0); SCALAR_FIELD(prcred_t, pr_ngroups, 1); ARRAY_FIELD(prcred_t, pr_groups, 0); END; } /* prpriv_t, */ static void gen_prpriv(void) { START(prpriv, prpriv_t); SCALAR_FIELD(prpriv_t, pr_nsets, 0); SCALAR_FIELD(prpriv_t, pr_setsize, 0); SCALAR_FIELD(prpriv_t, pr_infosize, 0); ARRAY_FIELD(prpriv_t, pr_sets, 0); END; } /* priv_impl_info_t, */ static void gen_priv_impl_info(void) { START(priv_impl_info, priv_impl_info_t); SCALAR_FIELD(priv_impl_info_t, priv_headersize, 0); SCALAR_FIELD(priv_impl_info_t, priv_flags, 0); SCALAR_FIELD(priv_impl_info_t, priv_nsets, 0); SCALAR_FIELD(priv_impl_info_t, priv_setsize, 0); SCALAR_FIELD(priv_impl_info_t, priv_max, 0); SCALAR_FIELD(priv_impl_info_t, priv_infosize, 0); SCALAR_FIELD(priv_impl_info_t, priv_globalinfosize, 0); END; } /* fltset_t, */ static void gen_fltset(void) { START(fltset, fltset_t); ARRAY_FIELD(fltset_t, word, 0); END; } /* * Layout description of siginfo_t, * * Note: many siginfo_t members are #defines mapping to * long dotted members of sub-structs or unions, and * we need the full member spec (with dots) for those. */ static void gen_siginfo(void) { START(siginfo, siginfo_t); SCALAR_FIELD(siginfo_t, si_signo, 0); SCALAR_FIELD(siginfo_t, si_errno, 0); SCALAR_FIELD(siginfo_t, si_code, 1); SCALAR_FIELD4(siginfo_t, si_value.sival_int, 0, "__data.__proc.__pdata.__kill.__value.sival_int"); SCALAR_FIELD4(siginfo_t, si_value.sival_ptr, 0, "__data.__proc.__pdata.__kill.__value.sival_ptr"); SCALAR_FIELD4(siginfo_t, si_pid, 0, "__data.__proc.__pid"); SCALAR_FIELD4(siginfo_t, si_uid, 0, "__data.__proc.__pdata.__kill.__uid"); SCALAR_FIELD4(siginfo_t, si_ctid, 0, "__data.__proc.__ctid"); SCALAR_FIELD4(siginfo_t, si_zoneid, 0, "__data.__proc.__zoneid"); SCALAR_FIELD4(siginfo_t, si_entity, 0, "__data.__rctl.__entity"); SCALAR_FIELD4(siginfo_t, si_addr, 0, "__data.__fault.__addr"); SCALAR_FIELD4(siginfo_t, si_status, 0, "__data.__proc.__pdata.__cld.__status"); SCALAR_FIELD4(siginfo_t, si_band, 0, "__data.__file.__band"); END; } /* sigset_t, */ static void gen_sigset(void) { START(sigset, sigset_t); ARRAY_FIELD(sigset_t, __sigbits, 0); END; } /* struct sigaction, */ static void gen_sigaction(void) { START(sigaction, struct sigaction); SCALAR_FIELD(struct sigaction, sa_flags, 0); SCALAR_FIELD4(struct sigaction, sa_handler, 0, "_funcptr._handler"); SCALAR_FIELD4(struct sigaction, sa_sigaction, 0, "_funcptr._sigaction"); SCALAR_FIELD(struct sigaction, sa_mask, 0); END; } /* stack_t, */ static void gen_stack(void) { START(stack, stack_t); SCALAR_FIELD(stack_t, ss_sp, 0); SCALAR_FIELD(stack_t, ss_size, 0); SCALAR_FIELD(stack_t, ss_flags, 0); END; } /* sysset_t, */ static void gen_sysset(void) { START(sysset, sysset_t); ARRAY_FIELD(sysset_t, word, 0); END; } /* timestruc_t, */ static void gen_timestruc(void) { START(timestruc, timestruc_t); SCALAR_FIELD(timestruc_t, tv_sec, 0); SCALAR_FIELD(timestruc_t, tv_nsec, 0); END; } /* struct utsname, */ static void gen_utsname(void) { START(utsname, struct utsname); ARRAY_FIELD(struct utsname, sysname, 0); ARRAY_FIELD(struct utsname, nodename, 0); ARRAY_FIELD(struct utsname, release, 0); ARRAY_FIELD(struct utsname, version, 0); ARRAY_FIELD(struct utsname, machine, 0); END; } static void gen_prfdinfo(void) { START(prfdinfo, prfdinfo_core_t); SCALAR_FIELD(prfdinfo_core_t, pr_fd, 0); SCALAR_FIELD(prfdinfo_core_t, pr_mode, 0); SCALAR_FIELD(prfdinfo_core_t, pr_uid, 0); SCALAR_FIELD(prfdinfo_core_t, pr_gid, 0); SCALAR_FIELD(prfdinfo_core_t, pr_major, 0); SCALAR_FIELD(prfdinfo_core_t, pr_minor, 0); SCALAR_FIELD(prfdinfo_core_t, pr_rmajor, 0); SCALAR_FIELD(prfdinfo_core_t, pr_rminor, 0); SCALAR_FIELD(prfdinfo_core_t, pr_ino, 0); SCALAR_FIELD(prfdinfo_core_t, pr_offset, 0); SCALAR_FIELD(prfdinfo_core_t, pr_size, 0); SCALAR_FIELD(prfdinfo_core_t, pr_fileflags, 0); SCALAR_FIELD(prfdinfo_core_t, pr_fdflags, 0); ARRAY_FIELD(prfdinfo_core_t, pr_path, 0); END; } static void gen_prsecflags(void) { START(prsecflags, prsecflags_t); SCALAR_FIELD(prsecflags_t, pr_version, 0); SCALAR_FIELD(prsecflags_t, pr_effective, 0); SCALAR_FIELD(prsecflags_t, pr_inherit, 0); SCALAR_FIELD(prsecflags_t, pr_lower, 0); SCALAR_FIELD(prsecflags_t, pr_upper, 0); END; } static void gen_prlwpname(void) { START(prlwpname, prlwpname_t); SCALAR_FIELD(prlwpname_t, pr_lwpid, 0); ARRAY_FIELD(prlwpname_t, pr_lwpname, 0); END; } static void gen_prupanic(void) { START(prupanic, prupanic_t); SCALAR_FIELD(prupanic_t, pru_version, 0); SCALAR_FIELD(prupanic_t, pru_flags, 0); ARRAY_FIELD(prupanic_t, pru_data, 0); END; } /*ARGSUSED*/ int main(int argc, char *argv[]) { const char *fmt = "\t&%s_layout,\n"; /* get obj file for input */ if (argc < 3) { (void) fprintf(stderr, "usage: %s {object_file} {MACH}\n", argv[0]); exit(1); } objfile = argv[1]; machname = argv[2]; get_ctf_file(objfile); (void) printf("#include \n"); gen_auxv(); gen_prgregset(); gen_lwpstatus(); gen_pstatus(); gen_prstatus(); gen_psinfo(); gen_prpsinfo(); gen_lwpsinfo(); gen_prcred(); gen_prpriv(); gen_priv_impl_info(); gen_fltset(); gen_siginfo(); gen_sigset(); gen_sigaction(); gen_stack(); gen_sysset(); gen_timestruc(); gen_utsname(); gen_prfdinfo(); gen_prsecflags(); gen_prlwpname(); gen_prupanic(); /* * Generate the full arch_layout description */ (void) printf( "\n\n\n\nstatic const sl_arch_layout_t layout_%s = {\n", machname); (void) printf(fmt, "auxv"); (void) printf(fmt, "fltset"); (void) printf(fmt, "lwpsinfo"); (void) printf(fmt, "lwpstatus"); (void) printf(fmt, "prcred"); (void) printf(fmt, "priv_impl_info"); (void) printf(fmt, "prpriv"); (void) printf(fmt, "psinfo"); (void) printf(fmt, "pstatus"); (void) printf(fmt, "prgregset"); (void) printf(fmt, "prpsinfo"); (void) printf(fmt, "prstatus"); (void) printf(fmt, "sigaction"); (void) printf(fmt, "siginfo"); (void) printf(fmt, "sigset"); (void) printf(fmt, "stack"); (void) printf(fmt, "sysset"); (void) printf(fmt, "timestruc"); (void) printf(fmt, "utsname"); (void) printf(fmt, "prfdinfo"); (void) printf(fmt, "prsecflags"); (void) printf(fmt, "prlwpname"); (void) printf(fmt, "prupanic"); (void) printf("};\n"); /* * A public function, to make the information available */ (void) printf("\n\nconst sl_arch_layout_t *\n"); (void) printf("struct_layout_%s(void)\n", machname); (void) printf("{\n\treturn (&layout_%s);\n}\n", machname); return (0); } /* * Helper functions using the CTF library to get type info. */ static void get_ctf_file(char *fname) { int ctferr; objfile = fname; if ((ctf = ctf_open(objfile, &ctferr)) == NULL) { errx(1, "Couldn't open object file %s: %s\n", objfile, ctf_errmsg(ctferr)); } } static void print_row(int boff, int eltlen, int nelts, int issigned, char *comment) { (void) printf("\t{ %d,\t%d,\t%d,\t%d },\t\t/* %s */\n", boff, eltlen, nelts, issigned, comment); } static void do_start(char *sname, char *tname) { do_start_name(sname); do_start_sizeof(tname, NULL); } static void do_start_name(char *sname) { (void) printf("\n\nstatic const sl_%s_layout_t %s_layout = {\n", sname, sname); } static void do_end(void) { (void) printf("};\n"); } static void do_start_sizeof(char *tname, char *rtname) { char comment[100]; ctf_id_t stype; int sz; if (rtname == NULL) rtname = tname; if ((stype = ctf_lookup_by_name(ctf, rtname)) == CTF_ERR) errx(1, "Couldn't find type %s", rtname); if ((stype = ctf_type_resolve(ctf, stype)) == CTF_ERR) errx(1, "Couldn't resolve type %s", tname); if ((sz = (int)ctf_type_size(ctf, stype)) < 0) { errx(1, "Couldn't get size for type %s", tname); } else if (sz == 0) { errx(1, "Invalid type size 0 for %s", tname); } (void) snprintf(comment, sizeof (comment), "sizeof (%s)", tname); print_row(0, sz, 0, 0, comment); } static void do_scalar_field(char *tname, char *fname, int _sign, char *dotfield) { int rc, off, sz, ftype; rc = get_field_info(tname, fname, dotfield, &off, &ftype); if (rc < 0) errx(1, "Can't get field info for %s->%s", tname, fname); if ((ftype = ctf_type_resolve(ctf, ftype)) == CTF_ERR) errx(1, "Couldn't resolve type of %s->%s", tname, fname); if ((sz = (int)ctf_type_size(ctf, ftype)) < 0) { errx(1, "Couldn't get size for type ID %d", ftype); } else if (sz == 0) { errx(1, "Invalid type size 0 for type ID %d", ftype); } print_row(off, sz, 0, _sign, fname); } static void do_array_field(char *tname, char *fname, int _sign, char *dotfield) { char comment[100]; ctf_arinfo_t ai; int typekind; int esz, rc, off, ftype; rc = get_field_info(tname, fname, dotfield, &off, &ftype); if (rc < 0) errx(1, "Can't get field info for %s->%s", tname, fname); if ((ftype = ctf_type_resolve(ctf, ftype)) == CTF_ERR) errx(1, "Couldn't resolve type of %s->%s", tname, fname); typekind = ctf_type_kind(ctf, ftype); if (typekind != CTF_K_ARRAY) errx(1, "Wrong type for %s->%s", tname, fname); rc = ctf_array_info(ctf, ftype, &ai); if (rc != 0) errx(1, "Can't get array info for %s->%s\n", tname, fname); esz = ctf_type_size(ctf, ai.ctr_contents); if (esz < 0) errx(1, "Can't get element size for %s->%s\n", tname, fname); (void) snprintf(comment, sizeof (comment), "%s[]", fname); print_row(off, esz, ai.ctr_nelems, _sign, comment); } static void do_array_type(char *tname, char *fname, int _sign) { ctf_arinfo_t ai; int stype, typekind; int esz, rc; if ((stype = ctf_lookup_by_name(ctf, tname)) == CTF_ERR) errx(1, "Couldn't find type %s", tname); if ((stype = ctf_type_resolve(ctf, stype)) == CTF_ERR) errx(1, "Couldn't resolve type %s", tname); typekind = ctf_type_kind(ctf, stype); if (typekind != CTF_K_ARRAY) errx(1, "Wrong type for %s->%s", tname, fname); rc = ctf_array_info(ctf, stype, &ai); if (rc != 0) errx(1, "Can't get array info for %s->%s\n", tname, fname); esz = ctf_type_size(ctf, ai.ctr_contents); if (esz < 0) errx(1, "Can't get element size for %s->%s\n", tname, fname); print_row(0, esz, ai.ctr_nelems, _sign, fname); } struct gfinfo { char *tname; /* top type name, i.e. the struct */ char *fname; /* field name */ char *dotname; /* full field name with dots (optional) */ char *prefix; /* current field search prefix */ int base_off; int fld_off; int fld_type; }; static int gfi_iter(const char *fname, ctf_id_t mbrtid, ulong_t off, void *varg); /* * Lookup field "fname" in type "tname". If "dotname" is non-NULL, * that's the full field name with dots, i.e. a_un.un_foo, which * we must search for by walking the struct CTF recursively. */ static int get_field_info(char *tname, char *fname, char *dotname, int *offp, int *tidp) { struct gfinfo gfi; ctf_id_t stype; int typekind; int rc; if ((stype = ctf_lookup_by_name(ctf, tname)) == CTF_ERR) errx(1, "Couldn't find type %s", tname); if ((stype = ctf_type_resolve(ctf, stype)) == CTF_ERR) errx(1, "Couldn't resolve type %s", tname); /* If fname has a dot, use it as dotname too. */ if (dotname == NULL && strchr(fname, '.') != NULL) dotname = fname; gfi.tname = tname; gfi.fname = fname; gfi.dotname = dotname; gfi.prefix = ""; gfi.base_off = 0; gfi.fld_off = 0; gfi.fld_type = 0; typekind = ctf_type_kind(ctf, stype); switch (typekind) { case CTF_K_STRUCT: case CTF_K_UNION: rc = ctf_member_iter(ctf, stype, gfi_iter, &gfi); break; default: errx(1, "Unexpected top-level type for %s", tname); break; } if (rc < 0) errx(1, "Error getting info for %s.%s", stype, fname); if (rc == 0) errx(1, "Did not find %s.%s", tname, fname); *offp = gfi.fld_off; *tidp = gfi.fld_type; return (0); } /* * Iteration callback for ctf_member_iter * Return <0 on error, 0 to keep looking, >0 for found. * * If no dotname, simple search for fieldname. * If we're asked to search with dotname, we need to do a full * recursive walk of the types under the dotname. */ int gfi_iter(const char *fieldname, ctf_id_t mbrtid, ulong_t off, void *varg) { char namebuf[100]; struct gfinfo *gfi = varg; char *saveprefix; int saveoff; int typekind; int byteoff; int len, rc; byteoff = gfi->base_off + (int)(off >> 3); /* Easy cases first: no dotname */ if (gfi->dotname == NULL) { if (strcmp(gfi->fname, fieldname) == 0) { gfi->fld_off = byteoff; gfi->fld_type = mbrtid; return (1); } return (0); } /* Exact match on the dotname? */ (void) snprintf(namebuf, sizeof (namebuf), "%s%s", gfi->prefix, fieldname); if (strcmp(gfi->dotname, namebuf) == 0) { gfi->fld_off = byteoff; gfi->fld_type = mbrtid; return (1); } /* * May need to recurse under this field, but * only if there's a match through '.' */ (void) strlcat(namebuf, ".", sizeof (namebuf)); len = strlen(namebuf); if (strncmp(gfi->dotname, namebuf, len) != 0) return (0); typekind = ctf_type_kind(ctf, mbrtid); switch (typekind) { case CTF_K_STRUCT: case CTF_K_UNION: break; default: return (0); } /* Recursively walk members */ saveprefix = gfi->prefix; saveoff = gfi->base_off; gfi->prefix = namebuf; gfi->base_off = byteoff; rc = ctf_member_iter(ctf, mbrtid, gfi_iter, gfi); gfi->prefix = saveprefix; gfi->base_off = saveoff; return (rc); }