0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi/*
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi * This file and its contents are supplied under the terms of the
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi * Common Development and Distribution License ("CDDL"), version 1.0.
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi * You may only use this file in accordance with the terms of version
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi * 1.0 of the CDDL.
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi *
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi * A full copy of the text of the CDDL should have accompanied this
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi * source. A copy of the CDDL is also available via the Internet at
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi * http://www.illumos.org/license/CDDL.
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi */
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi/*
2becb8cdf9cd77e1a76224f216be15d6ae3b9ec9Robert Mustacchi * Copyright (c) 2015 Joyent, Inc. All rights reserved.
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi */
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi/*
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi * ::typedef exists to allow a user to create and import auxiliary CTF
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi * information for the currently running target. ::typedef is similar to the C
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi * typedef keyword. However, ::typedef has no illusions of grandeur. It is not a
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi * standards complaint version of C's typedef. For specifics on what it does and
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi * does not support, please see the help message for ::typedef later on in this
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi * file.
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi *
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi * In addition to allowing the user to create types, it has a notion of a
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi * built-in set of types that a compiler might provide. Currently ::typedef
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi * supports both the standard illumos 32-bit and 64-bit environments, mainly
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi * LP32 and LP64. These are not present by default; it is up to the user to
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi * request that they be inserted.
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi *
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi * To facilitate this, ::typedef adds all of its type information to an
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi * auxiliary CTF container that is a part of the global mdb state. This is
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi * abstracted away from ::typedef by the mdb_ctf_* apis. This container is
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi * referred to as the synthetic container, as it holds these synthetic types.
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi * The synthetic container does not have a parent CTF container. This is rather
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi * important to its operation, as a user can end up referencing types that come
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi * from many different such containers (eg. different kernel modules). As such,
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi * whenever a type is referenced that we do not know about, we search all of the
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi * CTF containers that mdb knows about it. If we find it, then that type is
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi * imported (along with all of its dependent types) into the synthetic
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi * container.
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi *
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi * Finally, ::typedef can source CTF information from external files with the -r
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi * option. This will copy in every type from their container into the synthetic
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi * container, because of this the parent and child relationship between
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi * containers with parents cannot be maintained.
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi */
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi#include <mdb/mdb_modapi.h>
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi#include <mdb/mdb_ctf.h>
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi#include <mdb/mdb_list.h>
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi#include <mdb/mdb_nv.h>
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchistruct parse_node;
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi#define PN_F_POINTER 0x01
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi#define PN_F_ARRAY 0x02
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchitypedef struct parse_node {
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi mdb_list_t pn_list; /* list entry, must be first */
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi char *pn_type; /* name of base type */
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi char *pn_name; /* name of the member */
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi int pn_flags; /* flags */
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi int pn_nptrs; /* number of pointers */
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi int pn_asub; /* value of array subscript */
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi} parse_node_t;
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchitypedef struct parse_root {
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi mdb_list_t pr_nodes; /* list of members */
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi int pr_kind; /* CTF_K_* */
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi const char *pr_name; /* entity name */
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi const char *pr_tname; /* entity typedef */
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi} parse_root_t;
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchistatic int
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchitypedef_valid_identifier(const char *str)
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi{
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi /*
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi * We can't use the standard ctype.h functions because those aren't
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi * necessairly available in kmdb. On the flip side, we only care about
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi * ascii characters here so that isn't too bad.
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi *
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi * C Identifiers have to start with a letter or a _. Afterwards they can
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi * be alphanumeric or an _.
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi */
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi if (*str == '\0')
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi return (1);
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi if (*str != '_' &&
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi (*str < 'A' || *str > 'Z') &&
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi (*str < 'a' || *str > 'z'))
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi return (1);
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi str++;
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi while (*str != '\0') {
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi if (*str != '_' &&
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi (*str < '0' || *str > '9') &&
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi (*str < 'A' || *str > 'Z') &&
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi (*str < 'a' || *str > 'z'))
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi return (1);
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi str++;
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi }
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi return (0);
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi}
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi/*ARGSUSED*/
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchistatic int
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchitypedef_list_cb(mdb_ctf_id_t id, void *arg)
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi{
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi char buf[MDB_SYM_NAMLEN];
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi /*
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi * The user may have created an anonymous structure or union as part of
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi * running ::typedef. If this is the case, we passed a NULL pointer for
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi * the name into the ctf routines. When we go back and ask for the name
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi * of that, ctf goes through and loops through all the declarations.
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi * This, however correctly, gives us back something undesirable to the
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi * user, eg. the name is simply 'struct' and 'union'. Because a typedef
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi * will always have a non-anonymous name for that, we instead opt to
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi * not include these anonymous names. ctf usefully includes a space as
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi * part of that name.
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi */
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi (void) mdb_ctf_type_name(id, buf, sizeof (buf));
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi if (strcmp("struct ", buf) != 0 && strcmp("union ", buf) != 0)
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi mdb_printf("%s\n", buf);
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi return (0);
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi}
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchistatic char *
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchitypedef_join_strings(int nstr, const mdb_arg_t *args, int flags)
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi{
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi int i, size = 0;
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi char *ret, *sptr;
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi for (i = 0; i <= nstr; i++) {
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi /* Always account for the space or the null terminator */
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi size += strlen(args[i].a_un.a_str) + 1;
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi }
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi ret = mdb_alloc(sizeof (char) * size, flags);
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi if (ret == NULL)
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi return (NULL);
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi sptr = ret;
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi for (i = 0; i <= nstr; i++) {
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi (void) strcpy(sptr, args[i].a_un.a_str);
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi sptr += strlen(args[i].a_un.a_str);
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi *sptr = ' ';
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi sptr++;
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi }
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi *sptr = '\0';
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi return (ret);
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi}
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchistatic int
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchitypedef_list(void)
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi{
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi (void) mdb_ctf_type_iter(MDB_CTF_SYNTHETIC_ITER, typedef_list_cb,
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi NULL);
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi return (DCMD_OK);
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi}
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchistatic int
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchitypedef_destroy(void)
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi{
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi if (mdb_ctf_synthetics_reset() != 0) {
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi mdb_warn("failed to reset synthetic types");
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi return (DCMD_ERR);
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi }
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi return (DCMD_OK);
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi}
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi/*
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi * We've been asked to create the basic types that exist. We accept the
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi * following strings to indicate what we should create.
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi * - LP32, ILP32 (case insensitive)
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi * - LP64
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi */
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchistatic int
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchitypedef_create(const char *arg)
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi{
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi int kind;
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi if (strcasecmp(arg, "LP32") == 0 || strcasecmp(arg, "ILP32") == 0) {
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi kind = SYNTHETIC_ILP32;
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi } else if (strcasecmp(arg, "LP64") == 0) {
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi kind = SYNTHETIC_LP64;
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi } else {
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi mdb_printf("invalid data model: %s\n", arg);
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi return (DCMD_USAGE);
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi }
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi if (mdb_ctf_synthetics_create_base(kind) != 0) {
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi mdb_printf("failed to create intrinsic types, maybe "
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi "they already exist\n");
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi return (DCMD_ERR);
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi }
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi return (DCMD_OK);
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi}
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi/*
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi * Search the current arguments for a complete member declaration. This function
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi * modifies the value of defn based on what's necessary for parsing. It returns
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi * the appropriate parse node in pnp.
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi */
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchistatic int
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchitypedef_parse_member(char *defn, char **next, parse_node_t **pnp)
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi{
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi char *c, *name, *array;
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi int nptrs = 0;
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi parse_node_t *pn;
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi c = strchr(defn, ';');
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi if (c == NULL) {
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi mdb_printf("Cannot find semi-colon to delineate the end "
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi "of a member.\n");
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi return (DCMD_ERR);
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi }
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi *c = '\0';
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi *next = c + 1;
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi c = strrchr(defn, ' ');
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi if (c == NULL) {
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi mdb_printf("Missing both a name and a type declaration for "
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi "a member. Instead, found '%s'\n", defn);
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi return (DCMD_ERR);
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi }
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi *c = '\0';
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi name = c + 1;
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi c--;
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi while (*c == '*' || *c == ' ') {
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi if (*c == '*')
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi nptrs++;
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi c--;
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi }
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi *(c + 1) = '\0';
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi pn = mdb_zalloc(sizeof (parse_node_t), UM_SLEEP | UM_GC);
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi pn->pn_type = defn;
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi /*
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi * Go through and prepare the name field. Note that we still have to
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi * check if this is a pointer or an array. We also need to strip the
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi * ending semi-colon.
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi */
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi while (*name == '*') {
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi name++;
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi nptrs++;
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi }
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi if ((c = strchr(name, '[')) != NULL) {
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi array = c;
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi if ((c = strchr(array, ']')) == NULL) {
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi mdb_printf("Found the beginning of an array size "
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi "but no closing ']' in %s\n", array);
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi return (DCMD_ERR);
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi }
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi *array = '\0';
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi array++;
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi *c = '\0';
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi pn->pn_flags |= PN_F_ARRAY;
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi pn->pn_asub = mdb_strtoull(array);
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi if (pn->pn_asub < 0) {
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi mdb_printf("Array lengths cannot be negative\n");
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi return (DCMD_ERR);
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi }
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi }
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi if (typedef_valid_identifier(name) != 0) {
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi mdb_printf("The name %s is not a valid C identifier.\n",
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi name);
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi return (DCMD_ERR);
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi }
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi if (nptrs) {
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi pn->pn_flags |= PN_F_POINTER;
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi pn->pn_nptrs = nptrs;
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi }
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi pn->pn_name = name;
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi *pnp = pn;
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi return (DCMD_OK);
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi}
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi/*
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi * We're going to parse out our types here. Note that we are not strictly
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi * speaking a truely ANSI C compliant parser. Currently we support normal
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi * declarations except for the following:
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi * o function pointers
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi * o bit-fields
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi */
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchistatic int
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchitypedef_parse(char *defn, const char *name, parse_root_t **prp)
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi{
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi int len, ret;
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi const char *kind, *basename;
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi char *c, *brace;
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi parse_root_t *pr;
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi parse_node_t *pn;
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi mdb_ctf_id_t id;
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi pr = mdb_zalloc(sizeof (parse_root_t), UM_SLEEP | UM_GC);
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi basename = defn;
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi c = strchr(defn, ' ');
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi if (c == NULL) {
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi mdb_printf("Invalid structure definition. Structure "
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi "must start with either 'struct {' or 'union {'\n");
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi return (DCMD_ERR);
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi }
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi *c = '\0';
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi if (strcmp(defn, "struct") == 0)
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi pr->pr_kind = CTF_K_STRUCT;
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi else if (strcmp(defn, "union") == 0)
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi pr->pr_kind = CTF_K_UNION;
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi else {
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi mdb_printf("Invalid start of definition. "
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi "Expected 'struct' or 'union'. "
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi "Found: '%s'\n", defn);
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi return (DCMD_ERR);
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi }
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi /*
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi * We transform this back to a space so we can validate that a
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi * non-anonymous struct or union name is valid.
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi */
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi *c = ' ';
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi kind = defn;
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi defn = c + 1;
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi while (*defn == ' ')
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi defn++;
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi /* Check whether this is anonymous or not */
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi if (*defn != '{') {
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi brace = strchr(defn, '{');
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi c = brace;
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi if (c == NULL) {
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi mdb_printf("Missing opening brace for %s definition. "
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi "Expected '{'. "
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi "Found: '%c'\n", kind, *defn);
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi return (DCMD_ERR);
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi }
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi *c = '\0';
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi c--;
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi while (*c == ' ')
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi c--;
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi *(c+1) = '\0';
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi if (typedef_valid_identifier(defn) != 0) {
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi mdb_printf("The name %s is not a valid C identifier.\n",
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi defn);
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi return (DCMD_ERR);
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi }
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi if (mdb_ctf_lookup_by_name(basename, &id) != CTF_ERR) {
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi mdb_printf("type name %s already in use\n", basename);
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi return (DCMD_ERR);
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi }
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi pr->pr_name = defn;
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi defn = brace;
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi } else {
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi pr->pr_name = NULL;
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi }
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi defn++;
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi while (*defn == ' ')
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi defn++;
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi len = strlen(defn);
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi if (defn[len-1] != '}') {
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi mdb_printf("Missing closing brace for %s declaration. "
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi "Expected '}'.\n");
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi return (DCMD_ERR);
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi }
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi defn[len-1] = '\0';
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi /*
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi * Start walking all the arguments, looking for a terminating semicolon
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi * for type definitions.
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi */
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi for (;;) {
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi ret = typedef_parse_member(defn, &c, &pn);
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi if (ret == DCMD_ERR)
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi return (DCMD_ERR);
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi mdb_list_append(&pr->pr_nodes, pn);
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi while (*c == ' ')
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi c++;
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi if (*c == '\0')
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi break;
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi defn = c;
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi }
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi pr->pr_tname = name;
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi *prp = pr;
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi return (DCMD_OK);
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi}
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi/*
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi * Make sure that none of the member names overlap and that the type names don't
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi * already exist. If we have an array entry that is a VLA, make sure it is the
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi * last member and not the only member.
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi */
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchistatic int
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchitypedef_validate(parse_root_t *pr)
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi{
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi mdb_nv_t nv;
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi parse_node_t *pn;
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi mdb_ctf_id_t id;
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi int count = 0;
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi (void) mdb_nv_create(&nv, UM_SLEEP | UM_GC);
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi for (pn = mdb_list_next(&pr->pr_nodes); pn != NULL;
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi pn = mdb_list_next(pn)) {
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi count++;
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi if (mdb_nv_lookup(&nv, pn->pn_name) != NULL) {
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi mdb_printf("duplicate name detected: %s\n",
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi pn->pn_name);
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi return (DCMD_ERR);
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi }
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi /*
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi * Our parse tree won't go away before the nv, so it's simpler
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi * to just mark everything external.
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi */
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi (void) mdb_nv_insert(&nv, pn->pn_name, NULL, 0, MDB_NV_EXTNAME);
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi if (pn->pn_flags & PN_F_ARRAY && pn->pn_asub == 0) {
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi if (pr->pr_kind != CTF_K_STRUCT) {
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi mdb_printf("Flexible array members are only "
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi "valid in structs.\n");
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi return (DCMD_ERR);
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi }
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi if (&pn->pn_list != pr->pr_nodes.ml_prev) {
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi mdb_printf("Flexible array entries are only "
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi "allowed to be the last entry in a "
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi "struct\n");
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi return (DCMD_ERR);
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi }
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi if (count == 1) {
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi mdb_printf("Structs must have members aside "
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi "from a flexible member\n");
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi return (DCMD_ERR);
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi }
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi }
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi }
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi if (mdb_ctf_lookup_by_name(pr->pr_tname, &id) != CTF_ERR) {
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi mdb_printf("typedef name %s already exists\n", pr->pr_tname);
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi return (DCMD_ERR);
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi }
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi return (DCMD_OK);
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi}
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchistatic int
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchitypedef_add(parse_root_t *pr)
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi{
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi parse_node_t *pn;
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi mdb_ctf_id_t id, aid, tid, pid;
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi mdb_ctf_arinfo_t ar;
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi int ii;
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi /* Pre-flight checks */
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi if (typedef_validate(pr) == DCMD_ERR)
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi return (DCMD_ERR);
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi if (pr->pr_kind == CTF_K_STRUCT) {
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi if (mdb_ctf_add_struct(pr->pr_name, &id) != 0) {
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi mdb_printf("failed to create struct for %s\n",
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi pr->pr_tname);
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi return (DCMD_ERR);
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi }
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi } else {
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi if (mdb_ctf_add_union(pr->pr_name, &id) != 0) {
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi mdb_printf("failed to create union for %s\n",
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi pr->pr_tname);
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi return (DCMD_ERR);
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi }
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi }
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi for (pn = mdb_list_next(&pr->pr_nodes); pn != NULL;
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi pn = mdb_list_next(pn)) {
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi if (mdb_ctf_lookup_by_name(pn->pn_type, &tid) == CTF_ERR) {
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi mdb_printf("failed to add member %s: type %s does "
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi "not exist\n", pn->pn_name, pn->pn_type);
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi goto destroy;
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi }
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi if (pn->pn_flags & PN_F_POINTER) {
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi for (ii = 0; ii < pn->pn_nptrs; ii++) {
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi if (mdb_ctf_add_pointer(&tid,
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi &pid) != 0) {
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi mdb_printf("failed to add a pointer "
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi "type as part of member: %s\n",
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi pn->pn_name);
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi goto destroy;
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi }
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi tid = pid;
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi }
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi }
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi if (pn->pn_flags & PN_F_ARRAY) {
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi if (mdb_ctf_lookup_by_name("long", &aid) != 0) {
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi mdb_printf("failed to lookup the type 'long' "
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi "for array indexes, are you running mdb "
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi "without a target or using ::typedef -c?");
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi goto destroy;
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi }
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi ar.mta_contents = tid;
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi ar.mta_index = aid;
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi ar.mta_nelems = pn->pn_asub;
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi if (mdb_ctf_add_array(&ar, &tid) != 0) {
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi mdb_printf("failed to create array type for "
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi "memeber%s\n", pn->pn_name);
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi goto destroy;
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi }
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi }
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi if (mdb_ctf_add_member(&id, pn->pn_name, &tid, NULL) ==
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi CTF_ERR) {
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi mdb_printf("failed to create member %s\n",
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi pn->pn_name);
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi goto destroy;
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi }
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi }
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi if (mdb_ctf_add_typedef(pr->pr_tname, &id, NULL) != 0) {
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi mdb_printf("failed to add typedef for %s\n",
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi pr->pr_tname);
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi goto destroy;
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi }
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi return (DCMD_OK);
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchidestroy:
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi return (mdb_ctf_type_delete(&id));
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi}
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchistatic int
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchitypedef_readfile(const char *file)
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi{
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi int ret;
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi ret = mdb_ctf_synthetics_from_file(file);
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi if (ret != DCMD_OK)
2becb8cdf9cd77e1a76224f216be15d6ae3b9ec9Robert Mustacchi mdb_warn("failed to create synthetics from file %s\n", file);
2becb8cdf9cd77e1a76224f216be15d6ae3b9ec9Robert Mustacchi return (ret);
2becb8cdf9cd77e1a76224f216be15d6ae3b9ec9Robert Mustacchi}
2becb8cdf9cd77e1a76224f216be15d6ae3b9ec9Robert Mustacchi
2becb8cdf9cd77e1a76224f216be15d6ae3b9ec9Robert Mustacchistatic int
2becb8cdf9cd77e1a76224f216be15d6ae3b9ec9Robert Mustacchitypedef_writefile(const char *file)
2becb8cdf9cd77e1a76224f216be15d6ae3b9ec9Robert Mustacchi{
2becb8cdf9cd77e1a76224f216be15d6ae3b9ec9Robert Mustacchi int ret;
2becb8cdf9cd77e1a76224f216be15d6ae3b9ec9Robert Mustacchi
2becb8cdf9cd77e1a76224f216be15d6ae3b9ec9Robert Mustacchi ret = mdb_ctf_synthetics_to_file(file);
2becb8cdf9cd77e1a76224f216be15d6ae3b9ec9Robert Mustacchi if (ret != DCMD_OK)
2becb8cdf9cd77e1a76224f216be15d6ae3b9ec9Robert Mustacchi mdb_warn("failed to write synthetics to file %s", file);
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi return (ret);
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi}
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi/* ARGSUSED */
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchiint
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchicmd_typedef(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi{
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi mdb_ctf_id_t id;
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi int i;
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi int destroy = 0, list = 0;
2becb8cdf9cd77e1a76224f216be15d6ae3b9ec9Robert Mustacchi const char *cmode = NULL, *rfile = NULL, *wfile = NULL;
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi const char *dst, *src;
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi char *dup;
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi parse_root_t *pr;
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi if (flags & DCMD_ADDRSPEC)
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi return (DCMD_USAGE);
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi i = mdb_getopts(argc, argv,
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi 'd', MDB_OPT_SETBITS, TRUE, &destroy,
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi 'l', MDB_OPT_SETBITS, TRUE, &list,
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi 'c', MDB_OPT_STR, &cmode,
2becb8cdf9cd77e1a76224f216be15d6ae3b9ec9Robert Mustacchi 'r', MDB_OPT_STR, &rfile,
2becb8cdf9cd77e1a76224f216be15d6ae3b9ec9Robert Mustacchi 'w', MDB_OPT_STR, &wfile, NULL);
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi argc -= i;
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi argv += i;
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi /*
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi * All our options are mutually exclusive currently.
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi */
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi i = 0;
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi if (destroy)
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi i++;
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi if (cmode != NULL)
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi i++;
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi if (list)
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi i++;
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi if (rfile != NULL)
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi i++;
2becb8cdf9cd77e1a76224f216be15d6ae3b9ec9Robert Mustacchi if (wfile != NULL)
2becb8cdf9cd77e1a76224f216be15d6ae3b9ec9Robert Mustacchi i++;
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi if (i > 1)
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi return (DCMD_USAGE);
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi
2becb8cdf9cd77e1a76224f216be15d6ae3b9ec9Robert Mustacchi if ((destroy || cmode != NULL || list || rfile != NULL ||
2becb8cdf9cd77e1a76224f216be15d6ae3b9ec9Robert Mustacchi wfile != NULL) && argc != 0)
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi return (DCMD_USAGE);
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi if (destroy)
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi return (typedef_destroy());
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi if (cmode)
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi return (typedef_create(cmode));
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi if (list)
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi return (typedef_list());
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi if (rfile)
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi return (typedef_readfile(rfile));
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi
2becb8cdf9cd77e1a76224f216be15d6ae3b9ec9Robert Mustacchi if (wfile)
2becb8cdf9cd77e1a76224f216be15d6ae3b9ec9Robert Mustacchi return (typedef_writefile(wfile));
2becb8cdf9cd77e1a76224f216be15d6ae3b9ec9Robert Mustacchi
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi if (argc < 2)
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi return (DCMD_USAGE);
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi /*
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi * Check to see if we are defining a struct or union. Note that we have
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi * to distinguish between struct foo and struct {. All typedef structs
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi * are annonymous structs that are only known by their typedef name. The
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi * same is true with unions. The problem that we have to deal with is
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi * that the ';' character in mdb causes mdb to begin another command. To
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi * work around that fact we require users to put the whole struct
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi * definition in a pair of "" or ''.
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi */
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi if (argc == 2 && strchr(argv[0].a_un.a_str, '{') != NULL) {
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi dup = mdb_alloc(strlen(argv[0].a_un.a_str) + 1,
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi UM_GC | UM_SLEEP);
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi (void) strcpy(dup, argv[0].a_un.a_str);
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi if (typedef_parse(dup, argv[1].a_un.a_str, &pr) == DCMD_ERR)
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi return (DCMD_ERR);
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi if (typedef_add(pr) == DCMD_ERR)
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi return (DCMD_ERR);
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi return (DCMD_OK);
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi }
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi /*
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi * Someone could give us something like struct foobar or unsigned int or
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi * even long double imaginary. In this case we end up conjoining all
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi * arguments except the last one into one large string that we look up.
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi */
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi if (argc - 1 == 1) {
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi src = argv[0].a_un.a_str;
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi } else {
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi src = typedef_join_strings(argc - 2, argv, UM_GC | UM_SLEEP);
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi }
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi dst = argv[argc-1].a_un.a_str;
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi if (mdb_ctf_lookup_by_name(dst, &id) != -1) {
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi mdb_printf("%s already exists\n", dst);
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi return (DCMD_ERR);
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi }
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi if (mdb_ctf_lookup_by_name(src, &id) != 0) {
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi mdb_printf("%s does not exist\n", src);
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi return (DCMD_ERR);
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi }
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi if (mdb_ctf_add_typedef(dst, &id, NULL) != 0) {
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi mdb_printf("failed to create typedef\n");
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi return (DCMD_ERR);
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi }
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi return (DCMD_OK);
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi}
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchistatic char typedef_desc[] =
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi"::typedef operates like the C typedef keyword and creates a synthetic type\n"
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi"that is usable across mdb just like a type that is embedded in CTF data.\n"
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi"This includes familiar dcmds like ::print as well as mdb's tab completion\n"
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi"engine. The \"type\" argument can either be a named structure or union\n"
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi"declaration, like \"struct proc { int p_id; }\" declartion, an anonymous\n"
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi"structure or union declaration, like \"struct { int count; }\", or simply\n"
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi"the name of an existing type, like \"uint64_t\". Either form may refer to\n"
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi"other types already defined in CTF or a previous ::typedef invocation. When\n"
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi"debugging binaries without CTF, definitions for intrinsic types may be\n"
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi"created using the -c option. See the OPTIONS section for more information.\n"
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi"If a named struct or union is used, then a type will be created for it just\n"
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi"like in C. This may be used to mimic a forward declaration and an example of\n"
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi"this is in the EXAMPLES section. Regardless of whether a struct or union is\n"
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi"anonymous or named, the \"name\" argument is always required.\n"
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi"\n"
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi"When declaring anonymous structures and unions, the entire definition must\n"
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi"be enclosed within \"\" or ''. The ';' is used by mdb to separate commands\n"
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi"in a similar fashion to the shell. The ';' cannot be escaped, therefore\n"
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi"quoting your argument is necessary. See the EXAMPLES sections for examples\n"
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi"of what this looks like.\n"
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi"\n"
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi"All member and type names must be valid C identifiers. They must start with\n"
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi"an underscore or a letter. Subsequent characters are allowed to be letters,\n"
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi"numbers, or an underscore.\n"
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi"\n"
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi"Declaring arrays and any number of pointers in anonymous structures is \n"
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi"supported. However the following C features are not supported: \n"
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi" o function pointers (use a void * instead)\n"
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi" o bitfields (use an integer of the appropriate size instead)\n"
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi" o packed structures (all structures currently use their natural alignment)\n"
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi"\n"
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi"::typedef also allows you to read type definitions from a file. Definitions\n"
2becb8cdf9cd77e1a76224f216be15d6ae3b9ec9Robert Mustacchi"can be read from any ELF file that has a CTF section that libctf can parse\n"
2becb8cdf9cd77e1a76224f216be15d6ae3b9ec9Robert Mustacchi"or any raw CTF data files, such as those that can be created with ::typedef.\n"
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi"You can check if a file has such a section with elfdump(1). If a binary or\n"
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi"core dump does not have any type information, but you do have it elsewhere,\n"
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi"then you can use ::typedef -r to read in that type information.\n"
2becb8cdf9cd77e1a76224f216be15d6ae3b9ec9Robert Mustacchi"\n"
2becb8cdf9cd77e1a76224f216be15d6ae3b9ec9Robert Mustacchi"All built up definitions may be exported as a valid CTF container that can\n"
2becb8cdf9cd77e1a76224f216be15d6ae3b9ec9Robert Mustacchi"be used again with ::typedef -r or anything that uses libctf. To write them\n"
2becb8cdf9cd77e1a76224f216be15d6ae3b9ec9Robert Mustacchi"out, use ::typedef -w and specify the name of a file. For more information\n"
2becb8cdf9cd77e1a76224f216be15d6ae3b9ec9Robert Mustacchi"on the CTF file format, see ctf(4).\n"
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi"\n";
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchistatic char typedef_opts[] =
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi" -c model create intrinsic types based on the specified data model.\n"
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi" The INTRINSICS section lists the built-in types and typedefs.\n"
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi" The following data models are supported:\n"
2becb8cdf9cd77e1a76224f216be15d6ae3b9ec9Robert Mustacchi" o LP64 - Traditional illumos 64-bit program.\n"
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi" o LP32 - Traditional illumos 32-bit program.\n"
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi" o ILP32 - An alternate name for LP32.\n"
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi" -d delete all synthetic types\n"
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi" -l list all synthetic types\n"
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi" -r file import type definitions (CTF) from another ELF file\n"
2becb8cdf9cd77e1a76224f216be15d6ae3b9ec9Robert Mustacchi" -w file write all synthetic type definitions out to file\n"
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi"\n";
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchistatic char typedef_examps[] =
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi" ::typedef -c LP64\n"
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi" ::typedef uint64_t bender_t\n"
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi" ::typedef struct proc new_proc_t\n"
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi" ::typedef \"union { int frodo; char sam; long gandalf; }\" ringbearer_t;\n"
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi" ::typedef \"struct { uintptr_t stone[7]; void **white; }\" gift_t\n"
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi" ::typedef \"struct list { struct list *l_next; struct list *l_prev; }\" "
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi"list_t\n"
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi" ::typedef -r /var/tmp/qemu-system-x86_64\n"
2becb8cdf9cd77e1a76224f216be15d6ae3b9ec9Robert Mustacchi" ::typedef -w defs.ctf"
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi"\n";
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchistatic char typedef_intrins[] =
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi"The following C types and <stdint.h> typedefs are provided when \n"
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi"::typedef -c is used\n"
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi"\n"
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi" signed unsigned void\n"
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi" char short int\n"
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi" long long long signed char\n"
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi" signed short signed int signed long\n"
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi" singed long long unsigned char unsigned short\n"
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi" unsigned int unsigned long unsigned long long\n"
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi" _Bool float double\n"
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi" long double float imaginary double imaginary\n"
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi" long double imaginary float complex\n"
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi" double complex long double complex\n"
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi"\n"
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi" int8_t int16_t int32_t\n"
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi" int64_t intptr_t uint8_t\n"
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi" uint16_t uint32_t uint64_t\n"
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi" uchar_t ushort_t uint_t\n"
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi" ulong_t u_longlong_t ptrdiff_t\n"
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi" uintptr_t\n"
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi"\n";
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchivoid
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchicmd_typedef_help(void)
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi{
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi mdb_printf("%s", typedef_desc);
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi (void) mdb_dec_indent(2);
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi mdb_printf("%<b>OPTIONS%</b>\n");
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi (void) mdb_inc_indent(2);
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi mdb_printf("%s", typedef_opts);
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi (void) mdb_dec_indent(2);
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi mdb_printf("%<b>EXAMPLES%</b>\n");
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi (void) mdb_inc_indent(2);
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi mdb_printf("%s", typedef_examps);
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi (void) mdb_dec_indent(2);
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi mdb_printf("%<b>INTRINSICS%</b>\n");
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi (void) mdb_inc_indent(2);
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi mdb_printf("%s", typedef_intrins);
0a47c91c895e274dd0990009919e30e984364a8bRobert Mustacchi}