libctf, types: enhance ctf_type_aname to print function arg types
authorNick Alcock <nick.alcock@oracle.com>
Thu, 4 Jun 2020 14:25:32 +0000 (15:25 +0100)
committerNick Alcock <nick.alcock@oracle.com>
Wed, 22 Jul 2020 17:02:17 +0000 (18:02 +0100)
Somehow this never got implemented, which makes debugging any kind of
bug that has to do with argument types fantastically confusing, because
it *looks* like the func type takes no arguments though in fact it does.

This also lets us simplify the dumper slightly (and introduces our first
uses of ctf_assert and ctf_err_warn: there will be many more).

ctf_type_aname dumps function types without including the function
pointer name itself: ctf_dump search-and-replaces it in.  This seems to
give the nicest-looking results for existing users of both, even if it
is a bit fiddly.

libctf/
* ctf-types.c (ctf_type_aname): Print arg types here...
* ctf-dump.c (ctf_dump_funcs): ... not here: but do substitute
in the type name here.

libctf/ChangeLog
libctf/ctf-dump.c
libctf/ctf-types.c

index 114d4e6c9a0382ad25e4cb5e53e71e2c7f7ac9d6..288ad6e554dec83a15fd8765b8a310b04533ef7c 100644 (file)
@@ -1,3 +1,9 @@
+2020-07-22  Nick Alcock  <nick.alcock@oracle.com>
+
+       * ctf-types.c (ctf_type_aname): Print arg types here...
+       * ctf-dump.c (ctf_dump_funcs): ... not here: but do substitute
+       in the type name here.
+
 2020-07-22  Nick Alcock  <nick.alcock@oracle.com>
 
        * ctf-impl.h (ctf_assert): New.
index b8a81bc1ccf7e8b6f35f6d009c64f4e65d3e92c6..08d79f36d832564dc46eca67255d222bb1be1324 100644 (file)
@@ -397,13 +397,11 @@ ctf_dump_funcs (ctf_file_t *fp, ctf_dump_state_t *state)
   for (i = 0; i < fp->ctf_nsyms; i++)
     {
       char *str;
-      char *bit;
+      char *bit = NULL;
       const char *err;
       const char *sym_name;
       ctf_funcinfo_t fi;
       ctf_id_t type;
-      size_t j;
-      ctf_id_t *args;
 
       if ((type = ctf_func_info (state->cds_fp, i, &fi)) == CTF_ERR)
        switch (ctf_errno (state->cds_fp))
@@ -418,74 +416,65 @@ ctf_dump_funcs (ctf_file_t *fp, ctf_dump_state_t *state)
          case ECTF_NOFUNCDAT:
            continue;
          }
-      if ((args = calloc (fi.ctc_argc, sizeof (ctf_id_t))) == NULL)
-       return (ctf_set_errno (fp, ENOMEM));
 
-      /* Return type.  */
-      if ((str = ctf_type_aname (state->cds_fp, type)) == NULL)
+      /* Return type and all args.  */
+      if ((bit = ctf_type_aname (state->cds_fp, type)) == NULL)
        {
          err = "look up return type";
          goto err;
        }
 
-      str = str_append (str, " ");
-
-      /* Function name.  */
+      /* Replace in the returned string, dropping in the function name.  */
 
       sym_name = ctf_lookup_symbol_name (fp, i);
-      if (sym_name[0] == '\0')
+      if (sym_name[0] != '\0')
        {
-         if (asprintf (&bit, "0x%lx ", (unsigned long) i) < 0)
-           goto oom;
-       }
-      else
-       {
-         if (asprintf (&bit, "%s (0x%lx) ", sym_name, (unsigned long) i) < 0)
+         char *retstar;
+         char *new_bit;
+         char *walk;
+
+         new_bit = malloc (strlen (bit) + 1 + strlen (sym_name));
+         if (!new_bit)
            goto oom;
-       }
-      str = str_append (str, bit);
-      str = str_append (str, " (");
-      free (bit);
 
-      /* Function arguments.  */
+         /* See ctf_type_aname.  */
+         retstar = strstr (bit, "(*) (");
+         if (!ctf_assert (fp, retstar))
+           goto assert_err;
+         retstar += 2;                 /* After the '*' */
 
-      if (ctf_func_args (state->cds_fp, i, fi.ctc_argc, args) < 0)
-       {
-         err = "look up argument type";
-         goto err;
-       }
+         /* C is not good at search-and-replace.  */
+         walk = new_bit;
+         memcpy (walk, bit, retstar - bit);
+         walk += (retstar - bit);
+         strcpy (walk, sym_name);
+         walk += strlen (sym_name);
+         strcpy (walk, retstar);
 
-      for (j = 0; j < fi.ctc_argc; j++)
-       {
-         if ((bit = ctf_type_aname (state->cds_fp, args[j])) == NULL)
-           {
-             err = "look up argument type name";
-             goto err;
-           }
-         str = str_append (str, bit);
-         if ((j < fi.ctc_argc - 1) || (fi.ctc_flags & CTF_FUNC_VARARG))
-           str = str_append (str, ", ");
          free (bit);
+         bit = new_bit;
        }
 
-      if (fi.ctc_flags & CTF_FUNC_VARARG)
-       str = str_append (str, "...");
-      str = str_append (str, ")");
+      if (asprintf (&str, "Symbol 0x%lx: %s", (unsigned long) i, bit) < 0)
+       goto oom;
+      free (bit);
 
-      free (args);
       ctf_dump_append (state, str);
       continue;
 
+    err:
+      ctf_err_warn (fp, 1, "Cannot %s dumping function type for "
+                   "symbol 0x%li: %s", err, (unsigned long) i,
+                   ctf_errmsg (ctf_errno (state->cds_fp)));
+      free (bit);
+      return -1;               /* errno is set for us.  */
+
     oom:
-      free (args);
-      free (str);
+      free (bit);
       return (ctf_set_errno (fp, errno));
-    err:
-      ctf_dprintf ("Cannot %s dumping function type for symbol 0x%li: %s\n",
-                  err, (unsigned long) i,
-                  ctf_errmsg (ctf_errno (state->cds_fp)));
-      free (args);
-      free (str);
+
+    assert_err:
+      free (bit);
       return -1;               /* errno is set for us.  */
     }
   return 0;
index 550068250fda4edf974cce5527152c076673faf9..ddcca66a282446592f1ed6eb696fb19b4e4b80b9 100644 (file)
@@ -745,7 +745,51 @@ ctf_type_aname (ctf_file_t *fp, ctf_id_t type)
              ctf_decl_sprintf (&cd, "[%u]", cdp->cd_n);
              break;
            case CTF_K_FUNCTION:
-             ctf_decl_sprintf (&cd, "()");
+             {
+               size_t i;
+               ctf_funcinfo_t fi;
+               ctf_id_t *argv = NULL;
+
+               if (ctf_func_type_info (rfp, cdp->cd_type, &fi) < 0)
+                 goto err;             /* errno is set for us.  */
+
+               if ((argv = calloc (fi.ctc_argc, sizeof (ctf_id_t *))) == NULL)
+                 {
+                   ctf_set_errno (rfp, errno);
+                   goto err;
+                 }
+
+               if (ctf_func_type_args (rfp, cdp->cd_type,
+                                       fi.ctc_argc, argv) < 0)
+                 goto err;             /* errno is set for us.  */
+
+               ctf_decl_sprintf (&cd, "(*) (");
+               for (i = 0; i < fi.ctc_argc; i++)
+                 {
+                   char *arg = ctf_type_aname (rfp, argv[i]);
+
+                   if (arg == NULL)
+                     goto err;         /* errno is set for us.  */
+                   ctf_decl_sprintf (&cd, "%s", arg);
+                   free (arg);
+
+                   if ((i < fi.ctc_argc - 1)
+                       || (fi.ctc_flags & CTF_FUNC_VARARG))
+                     ctf_decl_sprintf (&cd, ", ");
+                 }
+
+               if (fi.ctc_flags & CTF_FUNC_VARARG)
+                 ctf_decl_sprintf (&cd, "...");
+               ctf_decl_sprintf (&cd, ")");
+
+               free (argv);
+               break;
+
+             err:
+               free (argv);
+               ctf_decl_fini (&cd);
+               return NULL;
+             }
              break;
            case CTF_K_STRUCT:
            case CTF_K_FORWARD: