]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
libctf, include, gdb: API review: rethink function type APIs
authorNick Alcock <nick.alcock@oracle.com>
Mon, 10 Nov 2025 17:56:42 +0000 (17:56 +0000)
committerNick Alcock <nick.alcock@oracle.com>
Tue, 9 Dec 2025 13:02:32 +0000 (13:02 +0000)
The existing interfaces for function type lookup were as follows:

 - ctf_func_type_info, which stuffed a bit of info about the function
   (return type, varags, number of args) into a structure
 - ctf_func_type_args, which took a big-enough structure and put arg
   info into it
 - ctf_func_type_arg_names (new in CTFv4), which did the same for a
   const char * array of arg names.
(and the ctf_func_info/args/arg_names by-symbol stuff we just deleted.)

This interface was always clunky, but with the addition of arg names it
become fearfully inconvenient, requiring the user to hand-allocate
things over and over again, and forcing the filling out of tiny
structures where simple parameters would do just as well.

Redo this completely, ripping out ctf_funcinfo_t and all three
ctf_func_type_* functions, replacing them with these:

/* Given a type ID relating to a function type or function linkage type, return
   an array of arg types, and optionally in the RET argument the return type
   too.  Vararg functions set CTF_FUNC_VARARG in the optional FLAG argument. The
   NARGS arg gives the length of the array (optional because it will always
   have the same value when you call both ctf_func_type and ctf_func_arg_names,
   so you only need to get it from one of them).  */

ctf_id_t *ctf_func_type (ctf_dict_t *, ctf_id_t type, ctf_id_t *ret_type,
 ctf_func_type_flags_t *flags, size_t *nargs);

/* Likewise, for the argument names.  */

const char **ctf_func_arg_names (ctf_dict_t *, ctf_id_t type, size_t *nargs);

Using these is *radically* easier because of the reduction of manual
allocation overhead, with only one tiny cost: if you only want to know
how many args a function has, but not anything about them, you have to
free the args ctf_func_type() returns now (and pay the cost of
populating it). If this really becomes a problem, we can fix it when
that happens.

(Look at the change to ctf_dedup_rhash_type for an example of the amount
of code redunction you can often expect.)

We also make the function flags into an enum while we're at it.

gdb/ctfread.c
include/ctf-api.h
libctf/ctf-create.c
libctf/ctf-dedup.c
libctf/ctf-types.c
libctf/libctf.ver
libctf/testsuite/libctf-writable/error-propagation.c
libctf/testsuite/libctf-writable/id-assignment.c
libctf/testsuite/libctf-writable/symtypetab-nonlinker-writeout.c

index 40339c3a8625403258f7be35ae4683a0451408c9..5b86405ba16b4320d628f671535dbd67318ae808 100644 (file)
@@ -603,34 +603,31 @@ read_func_kind_type (struct ctf_context *ccp, ctf_id_t tid)
   struct objfile *of = ccp->of;
   ctf_dict_t *dict = ccp->dict;
   struct type *type, *rettype, *atype;
-  ctf_funcinfo_t cfi;
-  uint32_t argc;
+  ctf_func_type_flags_t cflags;
+  ctf_id_t cret;
+  ctf_id_t *argv;
+  size_t argc;
 
   type = type_allocator (of, language_c).new_type ();
 
   type->set_code (TYPE_CODE_FUNC);
-  if (ctf_func_type_info (dict, tid, &cfi) < 0)
+  if ((argv = ctf_func_type (dict, tid, &cret, &cflags, &argc)) == NULL)
     {
       const char *fname = ctf_type_name_raw (dict, tid);
       error (_("Error getting function type info: %s"),
             fname == nullptr ? "noname" : fname);
     }
-  rettype = fetch_tid_type (ccp, cfi.ctc_return);
+  rettype = fetch_tid_type (ccp, cret);
   type->set_target_type (rettype);
   set_type_align (type, ctf_type_align (dict, tid));
 
   /* Set up function's arguments.  */
-  argc = cfi.ctc_argc;
   type->set_num_fields (argc);
-  if ((cfi.ctc_flags & CTF_FUNC_VARARG) != 0)
+  if ((cflags & CTF_FUNC_VARARG) != 0)
     type->set_has_varargs (true);
 
   if (argc != 0)
     {
-      std::vector<ctf_id_t> argv (argc);
-      if (ctf_func_type_args (dict, tid, argc, argv.data ()) == CTF_ERR)
-       return nullptr;
-
       type->alloc_fields (argc);
       struct type *void_type = builtin_type (of)->builtin_void;
       /* If failed to find the argument type, fill it with void_type.  */
@@ -643,7 +640,7 @@ read_func_kind_type (struct ctf_context *ccp, ctf_id_t tid)
            type->field (iparam).set_type (void_type);
        }
     }
-
+  free (argv);
   return set_tid_type (of, tid, type);
 }
 
index a34a981f377a0b90e4954a2a73fbd235ee71c304..722d7c4b83e7756b759d61791436f02d1182ba2a 100644 (file)
@@ -203,13 +203,6 @@ typedef struct ctf_arinfo
   size_t ctr_nelems;           /* Number of elements.  */
 } ctf_arinfo_t;
 
-typedef struct ctf_funcinfo
-{
-  ctf_id_t ctc_return;         /* Function return type.  */
-  size_t ctc_argc;             /* Number of typed arguments to function.  */
-  uint32_t ctc_flags;          /* Function attributes (see below).  */
-} ctf_funcinfo_t;
-
 typedef struct ctf_enum_value  /* The value of an enumerator.  Can just be
                                   cast to an int/int64 if you like. */
 {
@@ -238,7 +231,10 @@ typedef struct ctf_snapshot_id
   unsigned long snapshot_id;   /* Snapshot id at time of snapshot.  */
 } ctf_snapshot_id_t;
 
-#define        CTF_FUNC_VARARG 0x1     /* Function arguments end with varargs.  */
+typedef enum ctf_func_type_flags
+  {
+    CTF_FUNC_VARARG = 0x1      /* Function arguments end with varargs.  */
+  } ctf_func_type_flags_t;
 
 /* Functions that return a ctf_id_t use the following value to indicate failure.
    ctf_errno can be used to obtain an error code.  Functions that return
@@ -621,21 +617,19 @@ typedef enum ctf_btf_mode
 extern int ctf_version (int ctf_version_, size_t btf_hdr_len,
                        ctf_btf_mode_t btf_mode);
 
-/* Given a symbol table index corresponding to a function symbol, return info on
-   the type of a given function's arguments or return value, or its parameter
-   names.  Vararg functions have a final arg with CTF_FUNC_VARARG on in
-   ctc_flags.  */
+/* Given a type ID relating to a function type or function linkage type, return
+   an array of arg types, and optionally in the RET argument the return type
+   too.  Vararg functions set CTF_FUNC_VARARG in the optional FLAG argument. The
+   NARGS arg gives the length of the array (optional because it will always
+   have the same value when you call both ctf_func_type and ctf_func_arg_names,
+   so you only need to get it from one of them).  */
 
-extern int ctf_func_info (ctf_dict_t *, unsigned long, ctf_funcinfo_t *);
-extern int ctf_func_args (ctf_dict_t *, unsigned long, uint32_t, ctf_id_t *);
-extern int ctf_func_arg_names (ctf_dict_t *, unsigned long, uint32_t, const char **);
+extern ctf_id_t *ctf_func_type (ctf_dict_t *, ctf_id_t, ctf_id_t *ret_type,
+                               ctf_func_type_flags_t *flags, size_t *nargs);
 
-/* As above, but for CTF_K_FUNCTION or CTF_K_FUNC_LINKAGE types in CTF dicts.  */
+/* Likewise, for the argument names.  */
 
-extern int ctf_func_type_info (ctf_dict_t *, ctf_id_t, ctf_funcinfo_t *);
-extern int ctf_func_type_args (ctf_dict_t *, ctf_id_t, uint32_t, ctf_id_t *);
-extern int ctf_func_type_arg_names (ctf_dict_t *, ctf_id_t, uint32_t,
-                                   const char **);
+extern const char **ctf_func_arg_names (ctf_dict_t *, ctf_id_t, size_t *nargs);
 
 /* Get the linkage of a CTF_K_FUNC_LINKAGE or variable.  */
 
@@ -1005,9 +999,12 @@ extern ctf_id_t ctf_add_integer (ctf_dict_t *, uint32_t, const char *,
 /* ctf_add_function adds an unnamed function with a bundle of arguments and a
    return type.  ctf_add_function_linkage provides a function with a name
    and linkage, which is one of the CTF_FUNC_LINKAGE_* constants.  */
-extern ctf_id_t ctf_add_function (ctf_dict_t *, uint32_t,
-                                 const ctf_funcinfo_t *, const ctf_id_t *,
-                                 const char **arg_names);
+
+extern ctf_id_t ctf_add_function (ctf_dict_t *fp, uint32_t flag,
+                                 ctf_id_t ret_type, ctf_func_type_flags_t flags,
+                                 const ctf_id_t *argv, const char **arg_names,
+                                 size_t nargs);
+
 extern ctf_id_t ctf_add_function_linkage (ctf_dict_t *, uint32_t,
                                          ctf_id_t, const char *,
                                          ctf_linkages_t linkage);
index 733e4f00ba2f6768ecc4d89fc81b2479a1b415cd..95a3605fd4e9fdd368aacca76c9c09af9605c8d1 100644 (file)
@@ -1027,12 +1027,15 @@ ctf_add_tag (ctf_dict_t *fp, uint32_t flag, ctf_id_t type, const char *tag,
 
        case CTF_K_FUNCTION:
          {
-           ctf_funcinfo_t fi;
+           ctf_id_t *args;
+           size_t nargs;
 
-           if (ctf_func_type_info (fp, func_type, &fi) < 0)
+           if ((args = ctf_func_type (fp, func_type, NULL, NULL,
+                                      &nargs)) == NULL)
              return -1;        /* errno is set for us.  */
+           free (args);
 
-           if ((size_t) component_idx >= fi.ctc_argc)
+           if ((size_t) component_idx >= nargs)
              return (ctf_set_typed_errno (fp, ECTF_BADCOMPONENT));
 
            break;
@@ -1087,9 +1090,9 @@ ctf_add_decl_tag (ctf_dict_t *fp, uint32_t flag, ctf_id_t type, const char *tag,
 }
 
 ctf_id_t
-ctf_add_function (ctf_dict_t *fp, uint32_t flag,
-                 const ctf_funcinfo_t *ctc, const ctf_id_t *argv,
-                 const char **arg_names)
+ctf_add_function (ctf_dict_t *fp, uint32_t flag, ctf_id_t ret_type,
+                 ctf_func_type_flags_t flags, const ctf_id_t *argv,
+                 const char **arg_names, size_t nargs)
 {
   ctf_dtdef_t *dtd;
   uint32_t vlen;
@@ -1097,24 +1100,23 @@ ctf_add_function (ctf_dict_t *fp, uint32_t flag,
   ctf_dict_t *tmp = fp;
   size_t i;
 
-  if (ctc == NULL || (ctc->ctc_flags & ~CTF_FUNC_VARARG) != 0
-      || (ctc->ctc_argc != 0 && argv == NULL))
+  if ((flags & ~CTF_FUNC_VARARG) != 0 || (nargs != 0 && argv == NULL))
     return (ctf_set_typed_errno (fp, EINVAL));
 
-  vlen = ctc->ctc_argc;
+  vlen = nargs;
 
   /* UPTODO: CTF_K_BIG prefix for big functions?  */
   if (vlen > 0xffff)
     return (ctf_set_typed_errno (fp, EOVERFLOW));
 
-  if (ctc->ctc_flags & CTF_FUNC_VARARG)
+  if (flags & CTF_FUNC_VARARG)
     vlen++;           /* Add trailing zero to indicate varargs (see below).  */
 
-  if (ctc->ctc_return != 0
-      && ctf_lookup_by_id (&tmp, ctc->ctc_return, NULL) == NULL)
+  if (ret_type != 0
+      && ctf_lookup_by_id (&tmp, ret_type, NULL) == NULL)
     return CTF_ERR;                            /* errno is set for us.  */
 
-  for (i = 0; i < ctc->ctc_argc; i++)
+  for (i = 0; i < nargs; i++)
     {
       tmp = fp;
       if (argv[i] != 0 && ctf_lookup_by_id (&tmp, argv[i], NULL) == NULL)
@@ -1130,16 +1132,16 @@ ctf_add_function (ctf_dict_t *fp, uint32_t flag,
 
   vdat = (ctf_param_t *) dtd->dtd_vlen;
 
-  for (i = 0; i < ctc->ctc_argc; i++)
+  for (i = 0; i < nargs; i++)
     {
       vdat[i].cfp_name = ctf_str_add (fp, arg_names[i]);
       vdat[i].cfp_type = (uint32_t) argv[i];
     }
 
   dtd->dtd_data->ctt_info = CTF_TYPE_INFO (CTF_K_FUNCTION, 0, vlen);
-  dtd->dtd_data->ctt_type = (uint32_t) ctc->ctc_return;
+  dtd->dtd_data->ctt_type = (uint32_t) ret_type;
 
-  if (ctc->ctc_flags & CTF_FUNC_VARARG)
+  if (flags & CTF_FUNC_VARARG)
     {
       vdat[vlen - 1].cfp_type = 0;   /* Add trailing zero to indicate varargs.  */
       vdat[vlen - 1].cfp_name = 0;
@@ -2606,34 +2608,25 @@ ctf_add_type_internal (ctf_dict_t *dst_fp, ctf_dict_t *src_fp, ctf_id_t src_type
     /* UPTODO: FUNC_LINKAGE, DATASEC, VAR, *TAG */
     case CTF_K_FUNCTION:
       {
-       ctf_funcinfo_t fi;
+       ctf_func_type_flags_t flags;
+       ctf_id_t ret;
        ctf_id_t *argv;
+       size_t nargs;
        const char **arg_names;
        size_t i;
 
-       if (ctf_func_type_info (src_fp, src_type, &fi) < 0)
+       if ((argv = ctf_func_type (src_fp, src_type, &ret, &flags, &nargs)) == NULL)
          return CTF_ERR;                       /* errno is set for us. */
 
-       fi.ctc_return = ctf_add_type_internal (dst_fp, src_fp,
-                                              src_tp->ctt_type,
-                                              proc_tracking_fp);
+       ret = ctf_add_type_internal (dst_fp, src_fp, ret, proc_tracking_fp);
 
-       if (fi.ctc_return == CTF_ERR)
-         return CTF_ERR;                       /* errno is set for us.  */
-
-       if ((argv = calloc (fi.ctc_argc, sizeof (ctf_id_t *))) == NULL)
-         {
-           ctf_set_errno (src_fp, errno);
-           return CTF_ERR;
-         }
-
-       if (ctf_func_type_args (src_fp, src_type, fi.ctc_argc, argv) < 0)
+       if (ret == CTF_ERR)
          {
            free (argv);
-           return CTF_ERR;                     /* errno is set for us. */
+           return CTF_ERR;                     /* errno is set for us.  */
          }
 
-       for (i = 0; i < fi.ctc_argc; i++)
+       for (i = 0; i < nargs; i++)
          {
            argv[i] = ctf_add_type_internal (dst_fp, src_fp,
                                             argv[i],
@@ -2645,22 +2638,14 @@ ctf_add_type_internal (ctf_dict_t *dst_fp, ctf_dict_t *src_fp, ctf_id_t src_type
              }
          }
 
-       if ((arg_names = calloc (fi.ctc_argc, sizeof (const char **))) == NULL)
-         {
-           free (argv);
-           free (arg_names);
-           return CTF_ERR;                     /* errno is set for us. */
-         }
-
-       if (ctf_func_type_arg_names (src_fp, src_type, fi.ctc_argc,
-                                    arg_names) < 0)
+       if ((arg_names = ctf_func_arg_names (src_fp, src_type, NULL)) == NULL)
          {
            free (argv);
-           free (arg_names);
            return CTF_ERR;                     /* errno is set for us. */
          }
 
-       dst_type = ctf_add_function (dst_fp, flag, &fi, argv, arg_names);
+       dst_type = ctf_add_function (dst_fp, flag, ret, flags, argv, arg_names,
+                                    nargs);
        free (argv);
        free (arg_names);
        break;
index 086de7c56fe9cdcb1f1f56b4d10e1c6b0d0e3981..c6690cdd4eb459d84193961f2cdf8fc81c7dc86a 100644 (file)
@@ -989,64 +989,42 @@ ctf_dedup_rhash_type (ctf_dict_t *fp, ctf_dict_t *input, ctf_dict_t **inputs,
       }
     case CTF_K_FUNCTION:
       {
-       ctf_funcinfo_t fi;
+       ctf_id_t ret;
        ctf_id_t *args;
+       size_t nargs;
+       ctf_func_type_flags_t func_flags;
        const char **arg_names;
        uint32_t j;
 
-       if (ctf_func_type_info (input, type, &fi) < 0)
+       if ((args = ctf_func_type (input, type, &ret, &func_flags,
+                                  &nargs)) == NULL)
          {
-           whaterr = N_("error getting func type info");
+           whaterr = N_("error getting func arg info");
            goto input_err;
          }
 
        if ((hval = ctf_dedup_hash_type (fp, input, inputs, input_num,
-                                        fi.ctc_return, flags, depth,
+                                        ret, flags, depth,
                                         populate_fun)) == NULL)
          {
-           whaterr = N_("error getting func return type");
+           whaterr = N_("error hashing func return type");
            goto err;
          }
        ctf_dedup_sha1_add (&hash, hval, strlen (hval) + 1, "func return",
                            depth);
-       ctf_dedup_sha1_add (&hash, &fi.ctc_argc, sizeof (fi.ctc_argc),
-                           "func argc", depth);
-       ctf_dedup_sha1_add (&hash, &fi.ctc_flags, sizeof (fi.ctc_flags),
+       ctf_dedup_sha1_add (&hash, &nargs, sizeof (nargs), "func nargs", depth);
+       ctf_dedup_sha1_add (&hash, &func_flags, sizeof (func_flags),
                            "func flags", depth);
        ADD_CITER (citers, hval);
 
-       if ((args = calloc (fi.ctc_argc, sizeof (ctf_id_t))) == NULL)
-         {
-           err = ENOMEM;
-           whaterr = N_("error doing memory allocation");
-           goto err;
-         }
-
-       if ((args = calloc (fi.ctc_argc, sizeof (ctf_id_t))) == NULL)
-         {
-           err = ENOMEM;
-           whaterr = N_("error doing memory allocation");
-           goto err;
-         }
-
-       if ((arg_names = calloc (fi.ctc_argc, sizeof (const char **))) == NULL)
-         {
-           free (args);
-           err = ENOMEM;
-           whaterr = N_("error doing memory allocation");
-           goto err;
-         }
-
-       if ((ctf_func_type_args (input, type, fi.ctc_argc, args) < 0)
-           || (ctf_func_type_arg_names (input, type, fi.ctc_argc, arg_names) < 0))
+       if ((arg_names = ctf_func_arg_names (input, type, NULL)) == NULL)
          {
            free (args);
-           free (arg_names);
-           whaterr = N_("error getting func arg info");
+           whaterr = N_("error getting func arg names");
            goto input_err;
          }
 
-       for (j = 0; j < fi.ctc_argc; j++)
+       for (j = 0; j < nargs; j++)
          {
            ctf_dedup_sha1_add (&hash, arg_names[j], strlen (arg_names[j]) + 1,
                                "func arg name", depth);
@@ -2829,33 +2807,20 @@ ctf_dedup_rwalk_one_output_mapping (ctf_dict_t *output,
 
     case CTF_K_FUNCTION:
       {
-       ctf_funcinfo_t fi;
+       size_t nargs;
+       ctf_id_t func_ret;
        ctf_id_t *args;
        uint32_t j;
 
-       if (ctf_func_type_info (fp, type, &fi) < 0)
-         {
-           whaterr = N_("error during func type info lookup");
-           goto err_msg;
-         }
-
-       CTF_TYPE_WALK (fi.ctc_return, err,
-                      N_("error during func return type walk"));
-
-       if ((args = calloc (fi.ctc_argc, sizeof (ctf_id_t))) == NULL)
+       if ((args = ctf_func_type (fp, type, &func_ret, NULL, &nargs)) == NULL)
          {
-           whaterr = N_("error doing memory allocation");
+           whaterr = N_("error during func args lookup");
            goto err_msg;
          }
 
-       if (ctf_func_type_args (fp, type, fi.ctc_argc, args) < 0)
-         {
-           whaterr = N_("error doing func arg type lookup");
-           free (args);
-           goto err_msg;
-         }
+       CTF_TYPE_WALK (func_ret, err, N_("error during func return type walk"));
 
-       for (j = 0; j < fi.ctc_argc; j++)
+       for (j = 0; j < nargs; j++)
          CTF_TYPE_WALK (args[j], err_free_args,
                         N_("error during func arg type walk"));
        free (args);
@@ -3710,59 +3675,47 @@ ctf_dedup_emit_type (const char *hval, ctf_dict_t *output, ctf_dict_t **inputs,
 
     case CTF_K_FUNCTION:
       {
-       ctf_funcinfo_t fi;
+       size_t nargs;
+       ctf_id_t ret;
        ctf_id_t *args;
+       ctf_func_type_flags_t func_flags;
        const char **arg_names;
        uint32_t j;
 
        errtype = _("function");
-       if (ctf_func_type_info (input, type, &fi) < 0)
+       if ((args = ctf_func_type (input, type, &ret, &func_flags,
+                                  &nargs)) == NULL)
          goto err_input;
 
-       fi.ctc_return = ctf_dedup_id_to_target (output, target, inputs, ninputs,
-                                               parents, input, input_num,
-                                               fi.ctc_return);
-       if (fi.ctc_return == CTF_ERR)
-         goto err_input;
-
-       if ((args = calloc (fi.ctc_argc, sizeof (ctf_id_t))) == NULL)
-         {
-           ctf_set_errno (input, ENOMEM);
-           goto err_input;
-         }
-
-       errtype = _("function args");
-       if (ctf_func_type_args (input, type, fi.ctc_argc, args) < 0)
+       ret = ctf_dedup_id_to_target (output, target, inputs, ninputs,
+                                     parents, input, input_num, ret);
+       if (ret == CTF_ERR)
          {
            free (args);
            goto err_input;
          }
 
-       for (j = 0; j < fi.ctc_argc; j++)
+       for (j = 0; j < nargs; j++)
          {
            args[j] = ctf_dedup_id_to_target (output, target, inputs, ninputs,
                                              parents, input, input_num,
                                              args[j]);
            if (args[j] == CTF_ERR)
-             goto err_input;
-         }
-
-       if ((arg_names = calloc (fi.ctc_argc, sizeof (const char **))) == NULL)
-         {
-           ctf_set_errno (input, ENOMEM);
-           goto err_input;
+             {
+               free (args);
+               goto err_input;
+             }
          }
 
        errtype = _("function arg names");
-       if (ctf_func_type_arg_names (input, type, fi.ctc_argc, arg_names) < 0)
+       if ((arg_names = ctf_func_arg_names (input, type, NULL)) == NULL)
          {
            free (args);
-           free (arg_names);
            goto err_input;
          }
 
-       if ((new_type = ctf_add_function (target, isroot,
-                                         &fi, args, arg_names)) == CTF_ERR)
+       if ((new_type = ctf_add_function (target, isroot, ret, func_flags, args,
+                                         arg_names, nargs)) == CTF_ERR)
          {
            free (args);
            free (arg_names);
index 8c9303551e3ea814219c62de43cf58d1969c9659..8a679b5f952f3ed9870a759fa43cdebe99faefca 100644 (file)
@@ -1036,35 +1036,20 @@ ctf_type_aname (ctf_dict_t *fp, ctf_id_t type)
            case CTF_K_FUNCTION:
              {
                size_t i;
-               ctf_funcinfo_t fi;
-               ctf_id_t *argv = NULL;
+               ctf_id_t ret;
+               size_t nargs;
+               ctf_id_t *argv;
+               ctf_func_type_flags_t flags;
                const char **arg_names = NULL;
 
-               if (ctf_func_type_info (rfp, cdp->cd_type, &fi) < 0)
+               if ((argv = ctf_func_type (rfp, cdp->cd_type, &ret, &flags, &nargs)) == NULL)
                  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 ((arg_names = calloc (fi.ctc_argc, sizeof (const char *))) == 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.  */
-
-               if (ctf_func_type_arg_names (rfp, cdp->cd_type,
-                                            fi.ctc_argc, arg_names) < 0)
+               if ((arg_names = ctf_func_arg_names (rfp, cdp->cd_type, NULL)) == NULL)
                  goto err;             /* errno is set for us.  */
 
                ctf_decl_sprintf (&cd, "(*) (");
-               for (i = 0; i < fi.ctc_argc; i++)
+               for (i = 0; i < nargs; i++)
                  {
                    char *arg = ctf_type_aname (rfp, argv[i]);
 
@@ -1075,16 +1060,17 @@ ctf_type_aname (ctf_dict_t *fp, ctf_id_t type)
                                      ? arg_names[i] : "");
                    free (arg);
 
-                   if ((i < fi.ctc_argc - 1)
-                       || (fi.ctc_flags & CTF_FUNC_VARARG))
+                   if ((i < nargs - 1)
+                       || (flags & CTF_FUNC_VARARG))
                      ctf_decl_sprintf (&cd, ", ");
                  }
 
-               if (fi.ctc_flags & CTF_FUNC_VARARG)
+               if (flags & CTF_FUNC_VARARG)
                  ctf_decl_sprintf (&cd, "...");
                ctf_decl_sprintf (&cd, ")");
 
                free (argv);
+               free (arg_names);
                break;
 
              err:
@@ -1699,24 +1685,16 @@ ctf_tag (ctf_dict_t *fp, ctf_id_t tag)
     case CTF_K_FUNC_LINKAGE:
     case CTF_K_FUNCTION:
       {
-       ctf_funcinfo_t fi;
        ctf_id_t *args;
+       size_t nargs;
        ctf_id_t argtype;
 
-       if (ctf_func_type_info (fp, ref, &fi) < 0)
+       if ((args = ctf_func_type (fp, ref, NULL, NULL, &nargs)) == NULL)
          return CTF_ERR;       /* errno is set for us.  */
 
-       if (component_idx + 1 > (ssize_t) fi.ctc_argc)
+       if (component_idx + 1 > (ssize_t) nargs)
          break;
 
-       if ((args = malloc ((component_idx + 1) * sizeof (ctf_id_t))) == NULL)
-         return (ctf_set_typed_errno (fp, ENOMEM));
-
-       if (ctf_func_type_args (fp, ref, component_idx + 1, args))
-         {
-           free (args);
-           return CTF_ERR;     /* errno is set for us. */
-         }
        argtype = args[component_idx];
        free (args);
        return argtype;
@@ -2294,109 +2272,112 @@ ctf_struct_bitfield (ctf_dict_t * fp, ctf_id_t type)
   return CTF_INFO_KFLAG (tp->ctt_info);
 }
 
-/* Given a type ID relating to a function type, return info on return types and
-   arg counts for that function.  */
+/* Common code for ctf_func_type_*: arg checking, func arg vararg handling
+   etc.  */
 
-int
-ctf_func_type_info (ctf_dict_t *fp, ctf_id_t type, ctf_funcinfo_t *fip)
+static const ctf_param_t *
+ctf_func_type_common (ctf_dict_t **fp, ctf_id_t type, size_t *nargs,
+                     const ctf_type_t **suffix)
 {
-  ctf_dict_t *ofp = fp;
-  const ctf_type_t *tp, *suffix;
+  ctf_dict_t *ofp = *fp;
+  const ctf_type_t *tp;
   ctf_kind_t kind;
   unsigned char *vlen;
   const ctf_param_t *args;
 
-  if ((type = ctf_type_resolve (fp, type)) == CTF_ERR)
-    return -1;                 /* errno is set for us.  */
+  if ((type = ctf_type_resolve (*fp, type)) == CTF_ERR)
+    return NULL;               /* errno is set for us.  */
 
-  if (ctf_type_kind (fp, type) == CTF_K_FUNC_LINKAGE)
-    type = ctf_type_reference (fp, type);
+  if (ctf_type_kind (*fp, type) == CTF_K_FUNC_LINKAGE)
+    type = ctf_type_reference (*fp, type);
 
-  if ((tp = ctf_lookup_by_id (&fp, type, &suffix)) == NULL)
-    return -1;                 /* errno is set for us.  */
+  if ((tp = ctf_lookup_by_id (fp, type, suffix)) == NULL)
+    return NULL;               /* errno is set for us.  */
 
-  kind = LCTF_KIND (fp, tp);
+  kind = LCTF_KIND (*fp, tp);
   if (kind != CTF_K_FUNCTION)
-    return (ctf_set_errno (ofp, ECTF_NOTFUNC));
-
-  fip->ctc_return = suffix->ctt_type;
-  fip->ctc_flags = 0;
-
-  vlen = ctf_vlen (fp, type, tp, &fip->ctc_argc);
-  args = (const ctf_param_t *) vlen;
-
-  if (fip->ctc_argc != 0 && args[fip->ctc_argc - 1].cfp_type == 0)
     {
-      fip->ctc_flags |= CTF_FUNC_VARARG;
-      fip->ctc_argc--;
+      ctf_set_errno (ofp, ECTF_NOTFUNC);
+      return NULL;
     }
+  vlen = ctf_vlen (*fp, type, tp, nargs);
+  args = (const ctf_param_t *) vlen;
 
-  return 0;
-}
+  if (*nargs != 0 && args[*nargs - 1].cfp_type == 0)
+    (*nargs)--;
 
-/* Given a type ID relating to a function type, return the arguments for the
-   function.  */
+  return args;
+}
 
-int
-ctf_func_type_args (ctf_dict_t *fp, ctf_id_t type, uint32_t argc, ctf_id_t *argv)
+/* Given a type ID relating to a function type, return an array of arg types,
+   and optionally in the RET argument the return type too.  The optional FLAGS
+   argument may contain CTF_FUNC_* flags; the NARGS arg gives the length of
+   the array.  */
+ctf_id_t *
+ctf_func_type (ctf_dict_t *fp, ctf_id_t type, ctf_id_t *ret_type,
+              ctf_func_type_flags_t *flags, size_t *nargs)
 {
-  const ctf_type_t *tp;
+  ctf_dict_t *ofp = fp;
+  const ctf_type_t *suffix;
   const ctf_param_t *args;
-  unsigned char *vlen;
-  ctf_funcinfo_t f;
+  ctf_id_t *ret_args;
+  size_t n_args;
+  size_t i;
 
-  if ((type = ctf_type_resolve (fp, type)) == CTF_ERR)
-    return -1;                 /* errno is set for us.  */
+  if ((args = ctf_func_type_common (&fp, type, &n_args, &suffix)) == NULL)
+    return NULL;               /* errno is set for us.  */
 
-  if (ctf_type_kind (fp, type) == CTF_K_FUNC_LINKAGE)
-    type = ctf_type_reference (fp, type);
+  if (ret_type)
+    *ret_type = suffix->ctt_type;
 
-  if (ctf_func_type_info (fp, type, &f) < 0)
-    return -1;                 /* errno is set for us.  */
+  if (flags)
+    *flags = 0;
 
-  if ((tp = ctf_lookup_by_id (&fp, type, NULL)) == NULL)
-    return -1;                 /* errno is set for us.  */
+  if (n_args != 0 && args[n_args - 1].cfp_type == 0 && flags)
+    *flags |= CTF_FUNC_VARARG;
 
-  vlen = ctf_vlen (fp, type, tp, NULL);
-  args = (const ctf_param_t *) vlen;
+  if (nargs)
+    *nargs = n_args;
+
+  if ((ret_args = calloc (n_args, sizeof (ctf_id_t))) == NULL)
+    {
+      ctf_set_errno (ofp, ENOMEM);
+      return NULL;
+    }
 
-  for (argc = MIN (argc, f.ctc_argc); argc != 0; argc--)
-    *argv++ = (args++)->cfp_type;
+  for (i = 0; i < n_args; i++)
+    ret_args[i] = args[i].cfp_type;
 
-  return 0;
+  return ret_args;
 }
 
 /* Given a type ID relating to a function type, return the argument names for
    the function.  */
-
-int
-ctf_func_type_arg_names (ctf_dict_t *fp, ctf_id_t type, uint32_t argc,
-                        const char **arg_names)
+const char **
+ctf_func_arg_names (ctf_dict_t *fp, ctf_id_t type, size_t *nargs)
 {
-  const ctf_type_t *tp;
+  ctf_dict_t *ofp = fp;
   const ctf_param_t *args;
-  unsigned char *vlen;
-  ctf_funcinfo_t f;
+  const char **ret;
+  size_t n_args;
+  size_t i;
 
-  if ((type = ctf_type_resolve (fp, type)) == CTF_ERR)
-    return -1;                 /* errno is set for us.  */
+  if ((args = ctf_func_type_common (&fp, type, &n_args, NULL)) == NULL)
+    return NULL;               /* errno is set for us.  */
 
-  if (ctf_type_kind (fp, type) == CTF_K_FUNC_LINKAGE)
-    type = ctf_type_reference (fp, type);
+  if (nargs)
+    *nargs = n_args;
 
-  if (ctf_func_type_info (fp, type, &f) < 0)
-    return -1;                 /* errno is set for us.  */
-
-  if ((tp = ctf_lookup_by_id (&fp, type, NULL)) == NULL)
-    return -1;                 /* errno is set for us.  */
-
-  vlen = ctf_vlen (fp, type, tp, NULL);
-  args = (const ctf_param_t *) vlen;
+  if ((ret = calloc (n_args, sizeof (const char *))) == NULL)
+    {
+      ctf_set_errno (ofp, ENOMEM);
+      return NULL;
+    }
 
-  for (argc = MIN (argc, f.ctc_argc); argc != 0; argc--)
-    *arg_names++ = ctf_strptr (fp, (args++)->cfp_name);
+  for (i = 0; i < n_args; i++)
+    ret[i] = ctf_strptr (fp, args[i].cfp_name);
 
-  return 0;
+  return ret;
 }
 
 /* Get the linkage of a CTF_K_FUNC_LINKAGE or variable.  */
index cdc1a2743c5b2bd55604cf4c24274eaf2dfa83ba..5f74d427db13eeef333d464385809879d220c4eb 100644 (file)
@@ -47,9 +47,8 @@ LIBCTF_2.0 {
        ctf_errmsg;
        ctf_version;
 
-       ctf_func_type_info;
-       ctf_func_type_args;
-       ctf_func_type_arg_names;
+       ctf_func_type;
+       ctf_func_arg_names;
 
        ctf_lookup_by_name;
        ctf_lookup_by_kind;
index f695d0e545cbe3cf7784773ccb1aa7e6a1bb1ed7..ee8b36c2c968cad636153b150fd085d2301233d8 100644 (file)
@@ -62,7 +62,6 @@ int main (void)
   ctf_encoding_t long_encoding = { CTF_INT_SIGNED, 0, sizeof (long) };
   ctf_encoding_t void_encoding = { CTF_INT_SIGNED, 0, 0 };
   ctf_encoding_t foo;
-  ctf_funcinfo_t fi;
   ctf_id_t bar;
   int err;
 
@@ -145,21 +144,14 @@ int main (void)
   if (ctf_add_variable (parent, "base", base) < 0)
     goto child_err;
 
-  fi.ctc_return = void_id;
-  fi.ctc_argc = 0;
-  fi.ctc_flags = 0;
-  if ((function = ctf_add_function (child, CTF_ADD_ROOT, &fi, NULL)) == CTF_ERR)
+  if ((function = ctf_add_function (child, CTF_ADD_ROOT, void_id, NULL, NULL, 0)) == CTF_ERR)
     goto child_err;
 
-  desc = "func info lookup of non-function";
-  if ((ctf_func_type_info (child, base, &fi)) != CTF_ERR)
-    no_prop_err ();
-  check_prop_err (child, parent, ECTF_NOTFUNC);
-
-  desc = "func args lookup of non-function";
-  if ((ctf_func_type_args (child, base, 0, &bar)) != CTF_ERR)
+  desc = "func type lookup of non-function";
+  if ((bar = ctf_func_type (child, base, NULL, NULL, NULL)) != CTF_ERR)
     no_prop_err ();
   check_prop_err (child, parent, ECTF_NOTFUNC);
+  free (bar);
 
   /* Swap the insides of "parent" and "wrong" so we get a parent dict with
      different types than it had.  */
@@ -182,15 +174,11 @@ int main (void)
     no_prop_err ();
   check_prop_err (child, parent, ECTF_NONREPRESENTABLE);
 
-  desc = "func info lookup of nonrepresentable function";
-  if ((ctf_func_type_info (child, base, &fi)) != CTF_ERR)
-    no_prop_err ();
-  check_prop_err (child, parent, ECTF_NONREPRESENTABLE);
-
-  desc = "func args lookup of nonrepresentable function";
-  if ((ctf_func_type_args (child, base, 0, &bar)) != CTF_ERR)
+  desc = "func lookup of nonrepresentable function";
+  if ((bar = ctf_func_type_args (child, base, NULL, NULL, NULL)) != CTF_ERR)
     no_prop_err ();
   check_prop_err (child, parent, ECTF_NONREPRESENTABLE);
+  free (bar);
 
   desc = "child slice addition";
   if ((slice = ctf_add_slice (child, CTF_ADD_ROOT, base, &foo)) != CTF_ERR)
index 23efedf6e017f3f4566e07216b0926eaff1ea0f3..0640d73d7f84f24e73c0847e06ceb6b72643eb46 100644 (file)
@@ -23,9 +23,7 @@ test (int empty_parent, int unserialized_parent)
   ctf_id_t first_child_type = 1;
   ctf_membinfo_t memb;
   ctf_arinfo_t ar;
-  ctf_funcinfo_t func;
-  ctf_funcinfo_t pfunc, cfunc;
-  ctf_id_t args[2], pargs[2], cargs[2];
+  ctf_id_t args[2];
 
   printf ("Testing with %s, %s parent\n", empty_parent ? "empty" : "nonempty",
          unserialized_parent ? "unserialized" : "serialized");
@@ -90,13 +88,10 @@ test (int empty_parent, int unserialized_parent)
        goto parent_add_err;
       first_child_type++;
 
-      func.ctc_argc = 2;
-      func.ctc_flags = 0;
-      func.ctc_return = pprovint;
       args[0] = pptr;
       args[1] = parray;
 
-      if ((pfunction = ctf_add_function (parent, CTF_ADD_ROOT, &func, args)) == CTF_ERR)
+      if ((pfunction = ctf_add_function (parent, CTF_ADD_ROOT, pprovint, 0, args, 2)) == CTF_ERR)
        goto parent_add_err;
       first_child_type++;
     }
@@ -152,13 +147,10 @@ test (int empty_parent, int unserialized_parent)
       if (ctf_add_member (child, ctype2, "pfunc", pfunction, CTF_NEXT_MEMBER) < 0)
        goto child_add_memb_err;
 
-      func.ctc_argc = 2;
-      func.ctc_flags = 0;
-      func.ctc_return = pprovint;
       args[0] = pptr;
       args[1] = parray;
 
-      if ((cfunction = ctf_add_function (parent, CTF_ADD_ROOT, &func, args)) == CTF_ERR)
+      if ((cfunction = ctf_add_function (parent, CTF_ADD_ROOT, pprovint, 0, args, 2)) == CTF_ERR)
        goto child_add_err;
       first_child_type++;
 
@@ -341,6 +333,11 @@ test (int empty_parent, int unserialized_parent)
 
   if (!empty_parent)
     {
+      size_t pnargs, cnargs;
+      ctf_func_type_flags_t pflags, cflags;
+      ctf_id_t pret, cret;
+      ctf_id_t *pargs, *cargs;
+
       if (ctf_member_info (child, ctype2, "a", &memb) < 0)
        goto memb_err;
 
@@ -397,37 +394,28 @@ test (int empty_parent, int unserialized_parent)
        goto func_err;
       cfunction = memb.ctm_type;
 
-      if (ctf_func_type_info (child, pfunction, &pfunc) < 0 ||
-         ctf_func_type_info (child, cfunction, &cfunc) < 0)
+      if ((pargs = ctf_func_type (child, pfunction, &pret, &pflags, &pnargs)) == NULL
+         || (cargs = ctf_func_type (child, cfunction, &cret, &cflags, &cnargs)) == NULL)
        {
-         fprintf (stderr, "func info lookup failed: %s\n", ctf_errmsg (ctf_errno (child)));
+         fprintf (stderr, "func arg lookup failed: %s\n", ctf_errmsg (ctf_errno (child)));
          exit (1);
        }
 
-      if (memcmp (&pfunc, &cfunc, sizeof (pfunc)) != 0)
+      if (pnargs != cnargs || pflags != cflags || pret != cret)
        {
          fprintf (stderr, "parent and child funcs differ\n");
          exit (1);
        }
 
-      if (ctf_type_kind (child, pfunc.ctc_return) != CTF_K_INTEGER)
+      if (ctf_type_kind (child, pret) != CTF_K_INTEGER)
        {
          fprintf (stderr, "func return type lookup yielded kind %x, not %x\n", ctf_type_kind (child, pfunc.ctc_return), CTF_K_INTEGER);
          exit (1);
        }
 
-      /* This isn't a type ID, so we're not really expecting problems here, but if
-        there are problems, rather an error message than a buffer overrun.  */
-      if (pfunc.ctc_argc != 2)
+      if (pnargs != 2 || cnargs != 2)
        {
-         fprintf (stderr, "func has %i args, not 2\n", pfunc.ctc_argc);
-         exit (1);
-       }
-
-      if (ctf_func_type_args (child, pfunction, pfunc.ctc_argc, pargs) < 0 ||
-         ctf_func_type_args (child, cfunction, cfunc.ctc_argc, cargs) < 0)
-       {
-         fprintf (stderr, "func arg lookup failed: %s\n", ctf_errmsg (ctf_errno (child)));
+         fprintf (stderr, "funcs have (%i, %i) args, not 2\n", pnargs, cnargs);
          exit (1);
        }
 
index 819f60c85c534e4f11e824059b89395bec763859..d38be264527e3e7b6f2c179671339f0c8305f57b 100644 (file)
@@ -37,7 +37,6 @@ try_maybe_reporting (int report)
   ctf_id_t func, func2, func3, base, base2, base3;
   ctf_encoding_t e = { CTF_INT_SIGNED, 0, sizeof (long) };
   ctf_id_t dummy = 0;
-  ctf_funcinfo_t fi;
   ctf_next_t *i = NULL;
   ctf_id_t symtype;
   const char *symname;
@@ -60,9 +59,9 @@ try_maybe_reporting (int report)
   fi.ctc_return = base;
   fi.ctc_argc = 0;
   fi.ctc_flags = 0;
-  if (((func = ctf_add_function (fp, CTF_ADD_ROOT, &fi, &dummy)) == CTF_ERR) ||
-      ((func2 = ctf_add_function (fp, CTF_ADD_ROOT, &fi, &dummy)) == CTF_ERR) ||
-      ((func3 = ctf_add_function (fp, CTF_ADD_ROOT, &fi, &dummy)) == CTF_ERR))
+  if (((func = ctf_add_function (fp, CTF_ADD_ROOT, base, 0, &dummy, 0)) == CTF_ERR) ||
+      ((func2 = ctf_add_function (fp, CTF_ADD_ROOT, base, 0, &dummy, 0)) == CTF_ERR) ||
+      ((func3 = ctf_add_function (fp, CTF_ADD_ROOT, base, 0, &dummy, 0)) == CTF_ERR))
     goto create_types_err;
 
   /* Add some function and data symbols.  We intentionally add the symbols in