Print this page
cleanup
Rich's feedback
Address Robert's feedback
6375 Add native name demangling support

Split Close
Expand all
Collapse all
          --- old/usr/src/cmd/mdb/common/mdb/mdb_demangle.c
          +++ new/usr/src/cmd/mdb/common/mdb/mdb_demangle.c
↓ open down ↓ 14 lines elided ↑ open up ↑
  15   15   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  16   16   * If applicable, add the following below this CDDL HEADER, with the
  17   17   * fields enclosed by brackets "[]" replaced with your own identifying
  18   18   * information: Portions Copyright [yyyy] [name of copyright owner]
  19   19   *
  20   20   * CDDL HEADER END
  21   21   */
  22   22  /*
  23   23   * Copyright 2001-2002 Sun Microsystems, Inc.  All rights reserved.
  24   24   * Use is subject to license terms.
       25 + *
       26 + * Copyright 2018 Jason King
  25   27   */
  26   28  
  27      -#pragma ident   "%Z%%M% %I%     %E% SMI"
  28      -
  29   29  #include <mdb/mdb_modapi.h>
  30   30  #include <mdb/mdb_demangle.h>
  31   31  #include <mdb/mdb_err.h>
  32   32  #include <mdb/mdb.h>
  33   33  
  34      -#include <demangle.h>
  35   34  #include <strings.h>
  36   35  #include <unistd.h>
  37   36  #include <dlfcn.h>
  38   37  #include <link.h>
  39   38  
  40      -#ifdef _LP64
  41      -static const char LIB_DEMANGLE[] = "/usr/lib/64/libdemangle.so.1";
  42      -#else
  43      -static const char LIB_DEMANGLE[] = "/usr/lib/libdemangle.so.1";
  44      -#endif
       39 +static void *
       40 +mdb_dem_alloc(size_t len)
       41 +{
       42 +        return (mdb_alloc(len, UM_SLEEP));
       43 +}
  45   44  
       45 +static void
       46 +mdb_dem_free(void *p, size_t len)
       47 +{
       48 +        mdb_free(p, len);
       49 +}
       50 +
       51 +static sysdem_ops_t mdb_dem_demops = {
       52 +        .alloc = mdb_dem_alloc,
       53 +        .free = mdb_dem_free
       54 +};
       55 +
  46   56  mdb_demangler_t *
  47      -mdb_dem_load(const char *path)
       57 +mdb_dem_load(void)
  48   58  {
  49   59          mdb_demangler_t *dmp;
  50      -        void *hdl, *func;
  51   60  
  52      -        if (access(path, F_OK) == -1)
  53      -                return (NULL);
  54      -
  55      -        if ((hdl = dlmopen(LM_ID_BASE, path, RTLD_LAZY | RTLD_LOCAL)) == NULL) {
  56      -                (void) set_errno(EMDB_RTLD);
  57      -                return (NULL);
  58      -        }
  59      -
  60      -        if ((func = dlsym(hdl, "cplus_demangle")) == NULL) {
  61      -                (void) dlclose(hdl);
  62      -                (void) set_errno(EMDB_NODEM);
  63      -                return (NULL);
  64      -        }
  65      -
  66   61          dmp = mdb_alloc(sizeof (mdb_demangler_t), UM_SLEEP);
  67      -        (void) strncpy(dmp->dm_pathname, path, MAXPATHLEN);
  68      -        dmp->dm_pathname[MAXPATHLEN - 1] = '\0';
  69      -        dmp->dm_handle = hdl;
  70      -        dmp->dm_convert = (int (*)())func;
  71      -        dmp->dm_len = MDB_SYM_NAMLEN * 2;
  72      -        dmp->dm_buf = mdb_alloc(dmp->dm_len, UM_SLEEP);
       62 +        dmp->dm_len = 0;
       63 +        dmp->dm_buf = NULL;
  73   64          dmp->dm_flags = MDB_DM_SCOPE;
       65 +        /* stick with C++ for now to match old behavior */
       66 +        dmp->dm_lang = SYSDEM_LANG_CPP;
  74   67  
  75   68          return (dmp);
  76   69  }
  77   70  
  78   71  void
  79   72  mdb_dem_unload(mdb_demangler_t *dmp)
  80   73  {
  81      -        (void) dlclose(dmp->dm_handle);
  82   74          mdb_free(dmp->dm_buf, dmp->dm_len);
  83   75          mdb_free(dmp, sizeof (mdb_demangler_t));
  84   76  }
  85   77  
  86   78  static const char *
  87   79  mdb_dem_filter(mdb_demangler_t *dmp, const char *name)
  88   80  {
  89   81          static const char s_pref[] = "static ";
  90   82          static const char c_suff[] = " const";
  91   83          static const char v_suff[] = " volatile";
↓ open down ↓ 103 lines elided ↑ open up ↑
 195  187   * Take a name: (the foo`bar` is optional)
 196  188   *      foo`bar`__mangled_
 197  189   * and put:
 198  190   *      foo`bar`demangled
 199  191   * into dmp->dm_buf.  Point dmp->dm_dem to the beginning of the
 200  192   * demangled section of the result.
 201  193   */
 202  194  static int
 203  195  mdb_dem_process(mdb_demangler_t *dmp, const char *name)
 204  196  {
 205      -        char *buf = dmp->dm_buf;
 206      -        size_t len = dmp->dm_len;
      197 +        char *res = NULL;
      198 +        size_t reslen = 0;
 207  199  
 208  200          char *prefix = strrchr(name, '`');
 209      -        size_t prefixlen;
      201 +        size_t prefixlen = 0;
 210  202  
 211  203          if (prefix) {
 212  204                  prefix++;               /* the ` is part of the prefix */
 213  205                  prefixlen = prefix - name;
      206 +        }
 214  207  
 215      -                if (prefixlen >= len)
 216      -                        return (DEMANGLE_ESPACE);
      208 +        res = sysdemangle(name + prefixlen, dmp->dm_lang, &mdb_dem_demops);
      209 +        if (res == NULL) {
      210 +                if (errno != EINVAL)
      211 +                        mdb_warn("Error while demangling");
      212 +                return (-1);
      213 +        }
 217  214  
 218      -                (void) strncpy(buf, name, prefixlen);
      215 +        reslen = (res != NULL) ? strlen(res) : 0;
      216 +        reslen += prefixlen;
      217 +        reslen += 1;
 219  218  
 220      -                /*
 221      -                 * Fix up the arguments to dmp->dm_convert()
 222      -                 */
 223      -                name += prefixlen;
 224      -                buf += prefixlen;
 225      -                len -= prefixlen;
      219 +        if (reslen > dmp->dm_len) {
      220 +                mdb_free(dmp->dm_buf, dmp->dm_len);
      221 +
      222 +                dmp->dm_buf = mdb_zalloc(reslen, UM_SLEEP);
      223 +                if (dmp->dm_buf == NULL) {
      224 +                        dmp->dm_len = 0;
      225 +                        mdb_warn("Unable to allocate memory for demangling");
      226 +                        return (-1);
      227 +                }
      228 +                dmp->dm_len = reslen;
 226  229          }
 227  230  
      231 +        if (prefixlen > 0)
      232 +                (void) strlcpy(dmp->dm_buf, name, prefixlen + 1);
      233 +        else
      234 +                *dmp->dm_buf = '\0';
      235 +
      236 +        if (res != NULL) {
      237 +                (void) strlcat(dmp->dm_buf, res, dmp->dm_len);
      238 +                mdb_dem_free(res, strlen(res) + 1);
      239 +        }
      240 +
 228  241          /*
 229  242           * Save the position of the demangled string for mdb_dem_filter()
 230  243           */
 231      -        dmp->dm_dem = buf;
      244 +        dmp->dm_dem = dmp->dm_buf + prefixlen;
 232  245  
 233      -        return (dmp->dm_convert(name, buf, len));
      246 +        return (0);
 234  247  }
 235  248  
      249 +/* used by mdb_io.c:iob_addr2str */
 236  250  const char *
 237  251  mdb_dem_convert(mdb_demangler_t *dmp, const char *name)
 238  252  {
 239      -        int err;
      253 +        if (mdb_dem_process(dmp, name) != 0 ||
      254 +            strcmp(dmp->dm_buf, name) == 0)
      255 +                return (name);
 240  256  
 241      -        while ((err = mdb_dem_process(dmp, name)) == DEMANGLE_ESPACE) {
 242      -                size_t len = dmp->dm_len * 2;
 243      -                char *buf = mdb_alloc(len, UM_NOSLEEP);
 244      -
 245      -                if (buf == NULL) {
 246      -                        mdb_warn("failed to allocate memory for demangling");
 247      -                        return (name); /* just return original name */
 248      -                }
 249      -
 250      -                mdb_free(dmp->dm_buf, dmp->dm_len);
 251      -                dmp->dm_buf = buf;
 252      -                dmp->dm_len = len;
 253      -        }
 254      -
 255      -        if (err != 0 || strcmp(dmp->dm_buf, name) == 0)
 256      -                return (name); /* return original name if not mangled */
 257      -
 258  257          return (mdb_dem_filter(dmp, name));
 259  258  }
 260  259  
 261  260  /*ARGSUSED*/
 262  261  int
 263  262  cmd_demangle(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
 264  263  {
 265  264          mdb_demangler_t *dmp = mdb.m_demangler;
 266      -        const char *path = LIB_DEMANGLE;
 267  265  
 268      -        if (argc > 1 || (argc > 0 && argv->a_type != MDB_TYPE_STRING))
      266 +        if (argc > 0)
 269  267                  return (DCMD_USAGE);
 270  268  
 271      -        if (argc > 0) {
 272      -                if (dmp != NULL)
 273      -                        mdb_dem_unload(mdb.m_demangler);
 274      -                path = argv->a_un.a_str;
 275      -        }
 276      -
 277      -        if (dmp != NULL && argc == 0 && !(mdb.m_flags & MDB_FL_DEMANGLE)) {
      269 +        if (dmp != NULL && !(mdb.m_flags & MDB_FL_DEMANGLE)) {
 278  270                  mdb_printf("C++ symbol demangling enabled\n");
 279  271                  mdb.m_flags |= MDB_FL_DEMANGLE;
 280  272  
 281      -        } else if (dmp == NULL || argc > 0) {
 282      -                if ((mdb.m_demangler = mdb_dem_load(path)) != NULL) {
      273 +        } else if (dmp == NULL) {
      274 +                if ((mdb.m_demangler = mdb_dem_load()) != NULL) {
 283  275                          mdb_printf("C++ symbol demangling enabled\n");
 284  276                          mdb.m_flags |= MDB_FL_DEMANGLE;
 285  277                  } else {
 286      -                        mdb_warn("failed to load C++ demangler %s", path);
      278 +                        mdb_warn("no memory to load C++ demangler");
 287  279                          mdb.m_flags &= ~MDB_FL_DEMANGLE;
 288  280                  }
 289  281  
 290  282          } else {
 291  283                  mdb_dem_unload(mdb.m_demangler);
 292  284                  mdb.m_flags &= ~MDB_FL_DEMANGLE;
 293  285                  mdb.m_demangler = NULL;
 294  286                  mdb_printf("C++ symbol demangling disabled\n");
 295  287          }
 296  288  
↓ open down ↓ 34 lines elided ↑ open up ↑
 331  323  }
 332  324  
 333  325  /*ARGSUSED*/
 334  326  int
 335  327  cmd_demstr(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
 336  328  {
 337  329          if ((flags & DCMD_ADDRSPEC) || argc == 0)
 338  330                  return (DCMD_USAGE);
 339  331  
 340  332          if (mdb.m_demangler == NULL && (mdb.m_demangler =
 341      -            mdb_dem_load(LIB_DEMANGLE)) == NULL) {
 342      -                mdb_warn("failed to load C++ demangler %s", LIB_DEMANGLE);
      333 +            mdb_dem_load()) == NULL) {
      334 +                mdb_warn("failed to load demangler");
 343  335                  return (DCMD_ERR);
 344  336          }
 345  337  
 346  338          for (; argc != 0; argc--, argv++) {
 347  339                  mdb_printf("%s == %s\n", argv->a_un.a_str,
 348  340                      mdb_dem_convert(mdb.m_demangler, argv->a_un.a_str));
 349  341          }
 350  342  
 351  343          return (DCMD_OK);
 352  344  }
    
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX