From: Nick Alcock Date: Fri, 25 Apr 2025 09:55:41 +0000 (+0100) Subject: libctf: create, types: functions, linkage, arg names (API ADVICE) X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=39cdb3e395c27b3c337a9f6aa56ec3cad7dccbd5;p=thirdparty%2Fbinutils-gdb.git libctf: create, types: functions, linkage, arg names (API ADVICE) 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). --- diff --git a/include/ctf-api.h b/include/ctf-api.h index 079c4cf8784..92b602df4f2 100644 --- a/include/ctf-api.h +++ b/include/ctf-api.h @@ -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, diff --git a/libctf/ctf-create.c b/libctf/ctf-create.c index 5b558d54916..25876bbd583 100644 --- a/libctf/ctf-create.c +++ b/libctf/ctf-create.c @@ -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: diff --git a/libctf/ctf-decl.c b/libctf/ctf-decl.c index 4b1450d2ff1..e2b046d7325 100644 --- a/libctf/ctf-decl.c +++ b/libctf/ctf-decl.c @@ -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; diff --git a/libctf/ctf-lookup.c b/libctf/ctf-lookup.c index e06ecd78f67..64b19e02571 100644 --- a/libctf/ctf-lookup.c +++ b/libctf/ctf-lookup.c @@ -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); +} diff --git a/libctf/ctf-types.c b/libctf/ctf-types.c index bb2d652248c..8f19b566313 100644 --- a/libctf/ctf-types.c +++ b/libctf/ctf-types.c @@ -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_) diff --git a/libctf/libctf.ver b/libctf/libctf.ver index 605faa3e0e6..daa8375a9ed 100644 --- a/libctf/libctf.ver +++ b/libctf/libctf.ver @@ -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;