From: Nick Alcock Date: Mon, 10 Nov 2025 17:56:42 +0000 (+0000) Subject: libctf, include, gdb: API review: rethink function type APIs X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=291eb24b152509eefacb27bab571e402f77a3ee5;p=thirdparty%2Fbinutils-gdb.git libctf, include, gdb: API review: rethink function type APIs 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. --- diff --git a/gdb/ctfread.c b/gdb/ctfread.c index 40339c3a862..5b86405ba16 100644 --- a/gdb/ctfread.c +++ b/gdb/ctfread.c @@ -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 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); } diff --git a/include/ctf-api.h b/include/ctf-api.h index a34a981f377..722d7c4b83e 100644 --- a/include/ctf-api.h +++ b/include/ctf-api.h @@ -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); diff --git a/libctf/ctf-create.c b/libctf/ctf-create.c index 733e4f00ba2..95a3605fd4e 100644 --- a/libctf/ctf-create.c +++ b/libctf/ctf-create.c @@ -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; diff --git a/libctf/ctf-dedup.c b/libctf/ctf-dedup.c index 086de7c56fe..c6690cdd4eb 100644 --- a/libctf/ctf-dedup.c +++ b/libctf/ctf-dedup.c @@ -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); diff --git a/libctf/ctf-types.c b/libctf/ctf-types.c index 8c9303551e3..8a679b5f952 100644 --- a/libctf/ctf-types.c +++ b/libctf/ctf-types.c @@ -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. */ diff --git a/libctf/libctf.ver b/libctf/libctf.ver index cdc1a2743c5..5f74d427db1 100644 --- a/libctf/libctf.ver +++ b/libctf/libctf.ver @@ -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; diff --git a/libctf/testsuite/libctf-writable/error-propagation.c b/libctf/testsuite/libctf-writable/error-propagation.c index f695d0e545c..ee8b36c2c96 100644 --- a/libctf/testsuite/libctf-writable/error-propagation.c +++ b/libctf/testsuite/libctf-writable/error-propagation.c @@ -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) diff --git a/libctf/testsuite/libctf-writable/id-assignment.c b/libctf/testsuite/libctf-writable/id-assignment.c index 23efedf6e01..0640d73d7f8 100644 --- a/libctf/testsuite/libctf-writable/id-assignment.c +++ b/libctf/testsuite/libctf-writable/id-assignment.c @@ -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); } diff --git a/libctf/testsuite/libctf-writable/symtypetab-nonlinker-writeout.c b/libctf/testsuite/libctf-writable/symtypetab-nonlinker-writeout.c index 819f60c85c5..d38be264527 100644 --- a/libctf/testsuite/libctf-writable/symtypetab-nonlinker-writeout.c +++ b/libctf/testsuite/libctf-writable/symtypetab-nonlinker-writeout.c @@ -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