]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
libctf: create, types: functions, linkage, arg names (API ADVICE)
authorNick Alcock <nick.alcock@oracle.com>
Fri, 25 Apr 2025 09:55:41 +0000 (10:55 +0100)
committerNick Alcock <nick.alcock@oracle.com>
Fri, 25 Apr 2025 17:07:43 +0000 (18:07 +0100)
Functions change in CTFv4 by growing argument names as well as argument
types; the representation changes into a two-element array of (type, string
offset) rather than a simple array of arg types.  Functions also gain an
explicit linkage in a different type kind (CTF_K_FUNC_LINKAGE, which
corresponds to BTF_KIND_FUNC).

New API:

 typedef struct ctf_funcinfo {
 /* ... */
-  uint32_t ctc_argc; /* Number of typed arguments to function.  */
+  size_t ctc_argc; /* Number of typed arguments to function.  */
};

int ctf_func_arg_names (ctf_dict_t *, unsigned long, uint32_t, const char **);
int ctf_func_type_arg_names (ctf_dict_t *, ctf_id_t, uint32_t,
      const char **names);
+extern int ctf_type_linkage (ctf_dict_t *, ctf_id_t);
-extern ctf_id_t ctf_add_function (ctf_dict_t *, uint32_t,
-   const ctf_funcinfo_t *, const ctf_id_t *);
+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_linkage (ctf_dict_t *, uint32_t,
+   ctf_id_t, const char *, int linkage);

Adding this is fairly straightforward; the only annoying part is the way the
callers need to allocate space for the arg name and type arrays.  Maybe we
should rethink these into something like ctf_type_aname(), allocating
space for the caller so the caller doesn't need to?  It would certainly
make all the callers in libctf much less complex...

While we're at it, adjust ctf_type_reference, ctf_type_align, and
ctf_type_size for the new internal API changes (they also all have
special-case code for functions).

include/ctf-api.h
libctf/ctf-create.c
libctf/ctf-decl.c
libctf/ctf-lookup.c
libctf/ctf-types.c
libctf/libctf.ver

index 079c4cf8784256ffe304d955ada96daa9cc2291e..92b602df4f21ab706235d2f043e093b90ef5f86b 100644 (file)
@@ -167,7 +167,7 @@ typedef struct ctf_arinfo
 typedef struct ctf_funcinfo
 {
   ctf_id_t ctc_return;         /* Function return type.  */
-  uint32_t ctc_argc;           /* Number of typed arguments to function.  */
+  size_t ctc_argc;             /* Number of typed arguments to function.  */
   uint32_t ctc_flags;          /* Function attributes (see below).  */
 } ctf_funcinfo_t;
 
@@ -256,6 +256,7 @@ typedef struct ctf_snapshot_id
   _CTF_ITEM (ECTF_NOTBITSOU, "Type is not a bitfield-capable struct or union.") \
   _CTF_ITEM (ECTF_DESCENDING, "Structure offsets may not descend.") \
   _CTF_ITEM (ECTF_LINKAGE, "Invalid linkage.") \
+  _CTF_ITEM (ECTF_LINKKIND, "Only functions and variables have linkage.") \
   _CTF_ITEM (ECTF_NOTDATASEC, "This function requires a datasec.") \
   _CTF_ITEM (ECTF_NOTVAR, "This function requires a variable.") \
   _CTF_ITEM (ECTF_NODATASEC, "Variable not found in datasec.") \
@@ -536,16 +537,24 @@ extern const char *ctf_errmsg (int);
 extern int ctf_version (int);
 
 /* Given a symbol table index corresponding to a function symbol, return info on
-   the type of a given function's arguments or return value.  Vararg functions
-   have a final arg with CTF_FUNC_VARARG on in ctc_flags.  */
+   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.  */
 
 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 **);
 
-/* As above, but for CTF_K_FUNCTION types in CTF dicts.  */
+/* As above, but for CTF_K_FUNCTION or CTF_K_FUNC_LINKAGE types in CTF dicts.  */
 
 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 **);
+
+/* Get the linkage of a CTF_K_FUNC_LINKAGE or variable.  */
+
+extern int ctf_type_linkage (ctf_dict_t *, ctf_id_t);
 
 /* Look up function or data symbols by name and return their CTF type ID,
   if any.  (For both function symbols and data symbols that are function
@@ -887,11 +896,18 @@ extern ctf_id_t ctf_add_float (ctf_dict_t *, uint32_t,
                               const char *, const ctf_encoding_t *);
 extern ctf_id_t ctf_add_forward (ctf_dict_t *, uint32_t, const char *,
                                 uint32_t);
-extern ctf_id_t ctf_add_function (ctf_dict_t *, uint32_t,
-                                 const ctf_funcinfo_t *, const ctf_id_t *);
 extern ctf_id_t ctf_add_integer (ctf_dict_t *, uint32_t, const char *,
                                 const ctf_encoding_t *);
 
+/* 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_linkage (ctf_dict_t *, uint32_t,
+                                         ctf_id_t, const char *, int linkage);
+
 /* Add a "slice", which wraps some integral type and changes its encoding
    (useful for bitfields, etc).  In most respects slices are treated the same
    kind as the type they wrap: only ctf_type_reference can see the difference,
index 5b558d5491640635a51f2756da4f0d9f6f95875e..25876bbd5836ef5d2d89dcc52e5277430838b9b3 100644 (file)
@@ -888,14 +888,13 @@ ctf_set_array (ctf_dict_t *fp, ctf_id_t type, const ctf_arinfo_t *arp)
 
 ctf_id_t
 ctf_add_function (ctf_dict_t *fp, uint32_t flag,
-                 const ctf_funcinfo_t *ctc, const ctf_id_t *argv)
+                 const ctf_funcinfo_t *ctc, const ctf_id_t *argv,
+                 const char **arg_names)
 {
   ctf_dtdef_t *dtd;
-  ctf_id_t type;
   uint32_t vlen;
-  uint32_t *vdat;
+  ctf_param_t *vdat;
   ctf_dict_t *tmp = fp;
-  size_t initial_vbytes;
   size_t i;
 
   if (ctc == NULL || (ctc->ctc_flags & ~CTF_FUNC_VARARG) != 0
@@ -903,40 +902,77 @@ ctf_add_function (ctf_dict_t *fp, uint32_t flag,
     return (ctf_set_typed_errno (fp, EINVAL));
 
   vlen = ctc->ctc_argc;
+
+  /* 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)
     vlen++;           /* Add trailing zero to indicate varargs (see below).  */
 
   if (ctc->ctc_return != 0
-      && ctf_lookup_by_id (&tmp, ctc->ctc_return) == NULL)
+      && ctf_lookup_by_id (&tmp, ctc->ctc_return, NULL) == NULL)
     return CTF_ERR;                            /* errno is set for us.  */
 
+  for (i = 0; i < ctc->ctc_argc; i++)
+    {
+      tmp = fp;
+      if (argv[i] != 0 && ctf_lookup_by_id (&tmp, argv[i], NULL) == NULL)
+       return CTF_ERR;                         /* errno is set for us.  */
+    }
+
   if (vlen > CTF_MAX_VLEN)
     return (ctf_set_typed_errno (fp, EOVERFLOW));
 
-  /* One word extra allocated for padding for 4-byte alignment if need be.
-     Not reflected in vlen: we don't want to copy anything into it, and
-     it's in addition to (e.g.) the trailing 0 indicating varargs.  */
-
-  initial_vbytes = (sizeof (uint32_t) * (vlen + (vlen & 1)));
-  if ((type = ctf_add_generic (fp, flag, NULL, CTF_K_FUNCTION,
-                              initial_vbytes, &dtd)) == CTF_ERR)
+  if ((dtd = ctf_add_generic (fp, flag, NULL, CTF_K_FUNCTION, 0,
+                             sizeof (ctf_param_t) * vlen, 0, NULL)) == NULL)
     return CTF_ERR;                            /* errno is set for us.  */
 
-  vdat = (uint32_t *) dtd->dtd_vlen;
+  vdat = (ctf_param_t *) dtd->dtd_vlen;
 
   for (i = 0; i < ctc->ctc_argc; i++)
     {
-      tmp = fp;
-      if (argv[i] != 0 && ctf_lookup_by_id (&tmp, argv[i]) == NULL)
-       return CTF_ERR;                         /* errno is set for us.  */
-      vdat[i] = (uint32_t) argv[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, flag, vlen);
-  dtd->dtd_data.ctt_type = (uint32_t) ctc->ctc_return;
+  dtd->dtd_data->ctt_info = CTF_TYPE_INFO (CTF_K_FUNCTION, 0, vlen);
+  dtd->dtd_data->ctt_type = (uint32_t) ctc->ctc_return;
 
   if (ctc->ctc_flags & CTF_FUNC_VARARG)
-    vdat[vlen - 1] = 0;                   /* Add trailing zero to indicate varargs.  */
+    {
+      vdat[vlen - 1].cfp_type = 0;   /* Add trailing zero to indicate varargs.  */
+      vdat[vlen - 1].cfp_name = 0;
+    }
+
+  return dtd->dtd_type;
+}
+
+ctf_id_t
+ctf_add_function_linkage (ctf_dict_t *fp, uint32_t flag,
+                         ctf_id_t ref, const char *name, int linkage)
+{
+  ctf_dtdef_t *dtd;
+  ctf_dict_t *tmp = fp;
+
+  if (ref == CTF_ERR || ref > CTF_MAX_TYPE)
+    return (ctf_set_typed_errno (fp, EINVAL));
+
+  if (linkage < 0 || linkage > 2)
+    return (ctf_set_typed_errno (fp, ECTF_LINKAGE));
+
+  if (ref != 0 && ctf_lookup_by_id (&tmp, ref, NULL) == NULL)
+    return CTF_ERR;            /* errno is set for us.  */
+
+  if (ctf_type_kind (fp, ref) != CTF_K_FUNCTION)
+    return (ctf_set_typed_errno (fp, ECTF_NOTFUNC));
+
+  if ((dtd = ctf_add_generic (fp, flag, name, CTF_K_FUNC_LINKAGE, 0,
+                             0, 0, NULL)) == NULL)
+    return CTF_ERR;            /* errno is set for us.  */
+
+  dtd->dtd_data->ctt_info = CTF_TYPE_INFO (CTF_K_FUNC_LINKAGE, 0, linkage);
+  dtd->dtd_data->ctt_type = (uint32_t) ref;
 
   return dtd->dtd_type;
 }
@@ -1871,7 +1907,7 @@ ctf_add_funcobjt_sym_forced (ctf_dict_t *fp, int is_function, const char *name,
   if (fp->ctf_flags & LCTF_NO_TYPE)
     return (ctf_set_errno (fp, ECTF_NOTSERIALIZED));
 
-  if (ctf_lookup_by_id (&tmp, id) == NULL)
+  if (ctf_lookup_by_id (&tmp, id, NULL) == NULL)
     return -1;                         /* errno is set for us.  */
 
   if (is_function && ctf_type_kind (fp, id) != CTF_K_FUNCTION)
@@ -2176,8 +2212,6 @@ ctf_add_type_internal (ctf_dict_t *dst_fp, ctf_dict_t *src_fp, ctf_id_t src_type
   ctf_encoding_t src_en, dst_en;
   ctf_arinfo_t src_ar, dst_ar;
 
-  ctf_funcinfo_t ctc;
-
   ctf_id_t orig_src_type = src_type;
 
   if ((src_prefix = ctf_lookup_by_id (&src_fp, src_type, &src_tp)) == NULL)
@@ -2423,18 +2457,68 @@ ctf_add_type_internal (ctf_dict_t *dst_fp, ctf_dict_t *src_fp, ctf_id_t src_type
        dst_type = ctf_add_array (dst_fp, flag, &src_ar);
       break;
 
+    /* UPTODO: FUNC_LINKAGE, DATASEC, VAR, *TAG */
     case CTF_K_FUNCTION:
-      ctc.ctc_return = ctf_add_type_internal (dst_fp, src_fp,
-                                             src_tp->ctt_type,
-                                             proc_tracking_fp);
-      ctc.ctc_argc = 0;
-      ctc.ctc_flags = 0;
+      {
+       ctf_funcinfo_t fi;
+       ctf_id_t *argv;
+       const char **arg_names;
+       size_t i;
 
-      if (ctc.ctc_return == CTF_ERR)
-       return CTF_ERR;                         /* errno is set for us.  */
+       if (ctf_func_type_info (src_fp, src_type, &fi) < 0)
+         return CTF_ERR;                       /* errno is set for us. */
 
-      dst_type = ctf_add_function (dst_fp, flag, &ctc, NULL);
-      break;
+       fi.ctc_return = ctf_add_type_internal (dst_fp, src_fp,
+                                              src_tp->ctt_type,
+                                              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)
+         {
+           free (argv);
+           return CTF_ERR;                     /* errno is set for us. */
+         }
+
+       for (i = 0; i < fi.ctc_argc; i++)
+         {
+           argv[i] = ctf_add_type_internal (dst_fp, src_fp,
+                                            argv[i],
+                                            proc_tracking_fp);
+           if (argv[i] == CTF_ERR)
+             {
+               free (argv);
+               return CTF_ERR;                 /* errno is set for us.  */
+             }
+         }
+
+       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)
+         {
+           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);
+       free (argv);
+       free (arg_names);
+       break;
+      }
 
     case CTF_K_STRUCT:
     case CTF_K_UNION:
index 4b1450d2ff13ab1058cb1b5e1dcd6ff79781e254..e2b046d7325f4efe9bdb510c89ee93bf1962de75 100644 (file)
@@ -112,6 +112,11 @@ ctf_decl_push (ctf_decl_t *cd, ctf_dict_t *fp, ctf_id_t type)
       prec = CTF_PREC_BASE;
       break;
 
+    case CTF_K_FUNC_LINKAGE:
+      ctf_decl_push (cd, fp, suffix->ctt_type);
+      prec = CTF_PREC_FUNCTION;
+      break;
+
     case CTF_K_FUNCTION:
       ctf_decl_push (cd, fp, suffix->ctt_type);
       prec = CTF_PREC_FUNCTION;
index e06ecd78f67e0310436c968ef36370788f87faff..64b19e0257185b981e7fc8f5aeccae1060a12b39 100644 (file)
@@ -1407,3 +1407,21 @@ ctf_func_args (ctf_dict_t *fp, unsigned long symidx, uint32_t argc,
 
   return ctf_func_type_args (fp, type, argc, argv);
 }
+
+/* Given a symbol table index, return the argument names for the function
+   described by the corresponding entry in the symbol table.  */
+
+int
+ctf_func_arg_names (ctf_dict_t *fp, unsigned long symidx, uint32_t argc,
+                   const char **arg_names)
+{
+  ctf_id_t type;
+
+  if ((type = ctf_lookup_by_symbol (fp, symidx)) == CTF_ERR)
+    return -1;                                 /* errno is set for us.  */
+
+  if (ctf_type_kind (fp, type) != CTF_K_FUNCTION)
+    return (ctf_set_errno (fp, ECTF_NOTFUNC));
+
+  return ctf_func_type_arg_names (fp, type, argc, arg_names);
+}
index bb2d652248cec674aab84237446e87eeb7ce8e66..8f19b566313ce0204146618dfc1647a57a64ed56 100644 (file)
@@ -1082,6 +1082,7 @@ ctf_type_aname (ctf_dict_t *fp, ctf_id_t type)
                size_t i;
                ctf_funcinfo_t fi;
                ctf_id_t *argv = NULL;
+               const char **arg_names = NULL;
 
                if (ctf_func_type_info (rfp, cdp->cd_type, &fi) < 0)
                  goto err;             /* errno is set for us.  */
@@ -1092,10 +1093,20 @@ ctf_type_aname (ctf_dict_t *fp, ctf_id_t type)
                    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)
+                 goto err;             /* errno is set for us.  */
+
                ctf_decl_sprintf (&cd, "(*) (");
                for (i = 0; i < fi.ctc_argc; i++)
                  {
@@ -1103,7 +1114,9 @@ ctf_type_aname (ctf_dict_t *fp, ctf_id_t type)
 
                    if (arg == NULL)
                      goto err;         /* errno is set for us.  */
-                   ctf_decl_sprintf (&cd, "%s", arg);
+                   ctf_decl_sprintf (&cd, "%s%s%s", arg, arg_names[i] != 0 ?
+                                     " ":"", arg_names[i] != 0
+                                     ? arg_names[i] : "");
                    free (arg);
 
                    if ((i < fi.ctc_argc - 1)
@@ -1121,6 +1134,7 @@ ctf_type_aname (ctf_dict_t *fp, ctf_id_t type)
              err:
                ctf_set_errno (fp, ctf_errno (rfp));
                free (argv);
+               free (arg_names);
                ctf_decl_fini (&cd);
                return NULL;
              }
@@ -1135,6 +1149,23 @@ ctf_type_aname (ctf_dict_t *fp, ctf_id_t type)
            case CTF_K_ENUM64:
              ctf_decl_sprintf (&cd, "enum %s", name);
              break;
+           case CTF_K_FUNC_LINKAGE:
+           case CTF_K_VAR:
+             {
+               int linkage;
+               if ((linkage = ctf_type_linkage (fp, cdp->cd_type)) < 0)
+                 {
+                   ctf_set_errno (fp, ECTF_CORRUPT);
+                   ctf_decl_fini (&cd);
+                   return NULL;
+                 }
+
+               ctf_decl_sprintf (&cd, "%s%s", linkage == 0 ? "static "
+                                 : (linkage == 2 ? "extern " :
+                                    (linkage == 1 ? "" : "(invalid linkage) ")),
+                                 name);
+               break;
+             }
            case CTF_K_FORWARD:
              {
                switch (ctf_type_kind_forwarded (fp, cdp->cd_type))
@@ -1277,17 +1308,17 @@ ctf_type_size (ctf_dict_t *fp, ctf_id_t type)
   if ((type = ctf_type_resolve (fp, type)) == CTF_ERR)
     return -1;                 /* errno is set for us.  */
 
-  if ((tp = ctf_lookup_by_id (&fp, type)) == NULL)
+  if ((tp = ctf_lookup_by_id (&fp, type, NULL)) == NULL)
     return -1;                 /* errno is set for us.  */
 
-  switch (LCTF_INFO_KIND (fp, tp->ctt_info))
+  switch (LCTF_KIND (fp, tp))
     {
     case CTF_K_POINTER:
       return fp->ctf_dmodel->ctd_pointer;
 
     case CTF_K_FUNCTION:
-      return 0;                /* Function size is only known by symtab.  */
-
+    case CTF_K_FUNC_LINKAGE:
+      return 0;                        /* Function size is only known by symtab.  */
 
     case CTF_K_ARRAY:
       /* ctf_add_array() does not directly encode the element size, but
@@ -1383,14 +1414,15 @@ ctf_type_align (ctf_dict_t *fp, ctf_id_t type)
   if ((type = ctf_type_resolve (fp, type)) == CTF_ERR)
     return -1;                 /* errno is set for us.  */
 
-  if ((tp = ctf_lookup_by_id (&fp, type)) == NULL)
+  if ((tp = ctf_lookup_by_id (&fp, type, NULL)) == NULL)
     return -1;                 /* errno is set for us.  */
 
-  kind = LCTF_INFO_KIND (fp, tp->ctt_info);
+  kind = LCTF_KIND (fp, tp);
   switch (kind)
     {
     case CTF_K_POINTER:
     case CTF_K_FUNCTION:
+    case CTF_K_FUNC_LINKAGE:
       return fp->ctf_dmodel->ctd_pointer;
 
     case CTF_K_ARRAY:
@@ -1559,19 +1591,22 @@ ctf_id_t
 ctf_type_reference (ctf_dict_t *fp, ctf_id_t type)
 {
   ctf_dict_t *ofp = fp;
-  const ctf_type_t *tp;
+  const ctf_type_t *tp, *suffix;
 
-  if ((tp = ctf_lookup_by_id (&fp, type)) == NULL)
+  if ((tp = ctf_lookup_by_id (&fp, type, &suffix)) == NULL)
     return CTF_ERR;            /* errno is set for us.  */
 
-  switch (LCTF_INFO_KIND (fp, tp->ctt_info))
+  switch (LCTF_KIND (fp, tp))
     {
     case CTF_K_POINTER:
     case CTF_K_TYPEDEF:
     case CTF_K_VOLATILE:
     case CTF_K_CONST:
     case CTF_K_RESTRICT:
-      return tp->ctt_type;
+    case CTF_K_FUNCTION:
+    case CTF_K_FUNC_LINKAGE:
+    case CTF_K_VAR:
+      return suffix->ctt_type;
       /* Slices store their type in an unusual place.  */
     case CTF_K_SLICE:
       {
@@ -2147,34 +2182,31 @@ int
 ctf_func_type_info (ctf_dict_t *fp, ctf_id_t type, ctf_funcinfo_t *fip)
 {
   ctf_dict_t *ofp = fp;
-  const ctf_type_t *tp;
+  const ctf_type_t *tp, *suffix;
   uint32_t kind;
-  const uint32_t *args;
-  const ctf_dtdef_t *dtd;
-  ssize_t size, increment;
+  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 ((tp = ctf_lookup_by_id (&fp, type)) == NULL)
-    return -1;                 /* errno is set for us.  */
+  if (ctf_type_kind (fp, type) == CTF_K_FUNC_LINKAGE)
+    type = ctf_type_reference (fp, type);
 
-  (void) ctf_get_ctt_size (fp, tp, &size, &increment);
-  kind = LCTF_INFO_KIND (fp, tp->ctt_info);
+  if ((tp = ctf_lookup_by_id (&fp, type, &suffix)) == NULL)
+    return -1;                 /* errno is set for us.  */
 
+  kind = LCTF_KIND (fp, tp);
   if (kind != CTF_K_FUNCTION)
     return (ctf_set_errno (ofp, ECTF_NOTFUNC));
 
-  fip->ctc_return = tp->ctt_type;
+  fip->ctc_return = suffix->ctt_type;
   fip->ctc_flags = 0;
-  fip->ctc_argc = LCTF_INFO_VLEN (fp, tp->ctt_info);
 
-  if ((dtd = ctf_dynamic_type (fp, type)) == NULL)
-    args = (uint32_t *) ((uintptr_t) tp + increment);
-  else
-    args = (uint32_t *) dtd->dtd_vlen;
+  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] == 0)
+  if (fip->ctc_argc != 0 && args[fip->ctc_argc - 1].cfp_type == 0)
     {
       fip->ctc_flags |= CTF_FUNC_VARARG;
       fip->ctc_argc--;
@@ -2190,33 +2222,95 @@ int
 ctf_func_type_args (ctf_dict_t *fp, ctf_id_t type, uint32_t argc, ctf_id_t *argv)
 {
   const ctf_type_t *tp;
-  const uint32_t *args;
-  const ctf_dtdef_t *dtd;
-  ssize_t size, increment;
+  const ctf_param_t *args;
+  unsigned char *vlen;
   ctf_funcinfo_t f;
 
+  if ((type = ctf_type_resolve (fp, type)) == CTF_ERR)
+    return -1;                 /* errno is set for us.  */
+
+  if (ctf_type_kind (fp, type) == CTF_K_FUNC_LINKAGE)
+    type = ctf_type_reference (fp, type);
+
   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;
+
+  for (argc = MIN (argc, f.ctc_argc); argc != 0; argc--)
+    *argv++ = (args++)->cfp_type;
+
+  return 0;
+}
+
+/* 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 ctf_type_t *tp;
+  const ctf_param_t *args;
+  unsigned char *vlen;
+  ctf_funcinfo_t f;
+
   if ((type = ctf_type_resolve (fp, type)) == CTF_ERR)
     return -1;                 /* errno is set for us.  */
 
-  if ((tp = ctf_lookup_by_id (&fp, type)) == NULL)
+  if (ctf_type_kind (fp, type) == CTF_K_FUNC_LINKAGE)
+    type = ctf_type_reference (fp, type);
+
+  if (ctf_func_type_info (fp, type, &f) < 0)
     return -1;                 /* errno is set for us.  */
 
-  (void) ctf_get_ctt_size (fp, tp, &size, &increment);
+  if ((tp = ctf_lookup_by_id (&fp, type, NULL)) == NULL)
+    return -1;                 /* errno is set for us.  */
 
-  if ((dtd = ctf_dynamic_type (fp, type)) == NULL)
-    args = (uint32_t *) ((uintptr_t) tp + increment);
-  else
-    args = (uint32_t *) dtd->dtd_vlen;
+  vlen = ctf_vlen (fp, type, tp, NULL);
+  args = (const ctf_param_t *) vlen;
 
   for (argc = MIN (argc, f.ctc_argc); argc != 0; argc--)
-    *argv++ = *args++;
+    *arg_names++ = ctf_strptr (fp, (args++)->cfp_name);
 
   return 0;
 }
 
+/* Get the linkage of a CTF_K_FUNC_LINKAGE or variable.  */
+
+int
+ctf_type_linkage (ctf_dict_t *fp, ctf_id_t type)
+{
+  const ctf_type_t *tp;
+  const ctf_type_t *suffix;
+  unsigned char *vlen;
+  ctf_linkage_t *l;
+
+  int kind;
+
+  if ((tp = ctf_lookup_by_id (&fp, type, &suffix)) == NULL)
+    return -1;                 /* errno is set for us.  */
+
+  kind = ctf_type_kind_unsliced (fp, type);
+  if (kind != CTF_K_FUNC_LINKAGE && kind != CTF_K_VAR)
+    return ctf_set_errno (fp, ECTF_LINKKIND);
+
+  if (kind == CTF_K_VAR)
+    {
+      vlen = ctf_vlen (fp, type, tp, NULL);
+      l = (ctf_linkage_t *) vlen;
+
+      return l->ctl_linkage;
+    }
+
+  /* CTF_K_FUNC_LINKAGE.  */
+  return CTF_INFO_VLEN (suffix->ctt_info);
+}
+
 /* bsearch_r comparison function for datasec searches.  */
 static int
 search_datasec_by_offset (const void *key_, const void *arr_)
index 605faa3e0e66da3869d94666a8e26c5b52ffc209..daa8375a9ed32aeae40429ec5236c8d64f3d1949 100644 (file)
@@ -52,8 +52,10 @@ LIBCTF_2.0 {
 
        ctf_func_info;
        ctf_func_args;
+       ctf_func_arg_names;
        ctf_func_type_info;
        ctf_func_type_args;
+       ctf_func_type_arg_names;
 
        ctf_lookup_by_name;
        ctf_lookup_by_symbol;
@@ -76,6 +78,7 @@ LIBCTF_2.0 {
        ctf_type_kind;
        ctf_type_kind_forwarded;
        ctf_type_reference;
+       ctf_type_linkage;
        ctf_type_pointer;
        ctf_type_encoding;
        ctf_type_visit;
@@ -123,6 +126,7 @@ LIBCTF_2.0 {
        ctf_add_btf_float;
        ctf_add_forward;
        ctf_add_function;
+       ctf_add_function_linkage;
        ctf_add_integer;
        ctf_add_pointer;
        ctf_add_type;