aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Alcock <nick.alcock@oracle.com>2020-06-04 15:25:32 +0100
committerNick Alcock <nick.alcock@oracle.com>2020-07-22 18:02:17 +0100
commitc6e9a1e576ce4d948393b29e77b37e4ad934ee8f (patch)
tree9d1aa02a06b41c5c2cf446d5006152805f8b4c31
parent8b37e7b63ed77fa66e08c7dd08147db6a263d0fb (diff)
downloadfsf-binutils-gdb-c6e9a1e576ce4d948393b29e77b37e4ad934ee8f.zip
fsf-binutils-gdb-c6e9a1e576ce4d948393b29e77b37e4ad934ee8f.tar.gz
fsf-binutils-gdb-c6e9a1e576ce4d948393b29e77b37e4ad934ee8f.tar.bz2
libctf, types: enhance ctf_type_aname to print function arg types
Somehow this never got implemented, which makes debugging any kind of bug that has to do with argument types fantastically confusing, because it *looks* like the func type takes no arguments though in fact it does. This also lets us simplify the dumper slightly (and introduces our first uses of ctf_assert and ctf_err_warn: there will be many more). ctf_type_aname dumps function types without including the function pointer name itself: ctf_dump search-and-replaces it in. This seems to give the nicest-looking results for existing users of both, even if it is a bit fiddly. libctf/ * ctf-types.c (ctf_type_aname): Print arg types here... * ctf-dump.c (ctf_dump_funcs): ... not here: but do substitute in the type name here.
-rw-r--r--libctf/ChangeLog6
-rw-r--r--libctf/ctf-dump.c87
-rw-r--r--libctf/ctf-types.c46
3 files changed, 89 insertions, 50 deletions
diff --git a/libctf/ChangeLog b/libctf/ChangeLog
index 114d4e6..288ad6e 100644
--- a/libctf/ChangeLog
+++ b/libctf/ChangeLog
@@ -1,5 +1,11 @@
2020-07-22 Nick Alcock <nick.alcock@oracle.com>
+ * ctf-types.c (ctf_type_aname): Print arg types here...
+ * ctf-dump.c (ctf_dump_funcs): ... not here: but do substitute
+ in the type name here.
+
+2020-07-22 Nick Alcock <nick.alcock@oracle.com>
+
* ctf-impl.h (ctf_assert): New.
(ctf_err_warning_t): Likewise.
(ctf_file_t) <ctf_errs_warnings>: Likewise.
diff --git a/libctf/ctf-dump.c b/libctf/ctf-dump.c
index b8a81bc..08d79f3 100644
--- a/libctf/ctf-dump.c
+++ b/libctf/ctf-dump.c
@@ -397,13 +397,11 @@ ctf_dump_funcs (ctf_file_t *fp, ctf_dump_state_t *state)
for (i = 0; i < fp->ctf_nsyms; i++)
{
char *str;
- char *bit;
+ char *bit = NULL;
const char *err;
const char *sym_name;
ctf_funcinfo_t fi;
ctf_id_t type;
- size_t j;
- ctf_id_t *args;
if ((type = ctf_func_info (state->cds_fp, i, &fi)) == CTF_ERR)
switch (ctf_errno (state->cds_fp))
@@ -418,74 +416,65 @@ ctf_dump_funcs (ctf_file_t *fp, ctf_dump_state_t *state)
case ECTF_NOFUNCDAT:
continue;
}
- if ((args = calloc (fi.ctc_argc, sizeof (ctf_id_t))) == NULL)
- return (ctf_set_errno (fp, ENOMEM));
- /* Return type. */
- if ((str = ctf_type_aname (state->cds_fp, type)) == NULL)
+ /* Return type and all args. */
+ if ((bit = ctf_type_aname (state->cds_fp, type)) == NULL)
{
err = "look up return type";
goto err;
}
- str = str_append (str, " ");
-
- /* Function name. */
+ /* Replace in the returned string, dropping in the function name. */
sym_name = ctf_lookup_symbol_name (fp, i);
- if (sym_name[0] == '\0')
+ if (sym_name[0] != '\0')
{
- if (asprintf (&bit, "0x%lx ", (unsigned long) i) < 0)
- goto oom;
- }
- else
- {
- if (asprintf (&bit, "%s (0x%lx) ", sym_name, (unsigned long) i) < 0)
+ char *retstar;
+ char *new_bit;
+ char *walk;
+
+ new_bit = malloc (strlen (bit) + 1 + strlen (sym_name));
+ if (!new_bit)
goto oom;
- }
- str = str_append (str, bit);
- str = str_append (str, " (");
- free (bit);
- /* Function arguments. */
+ /* See ctf_type_aname. */
+ retstar = strstr (bit, "(*) (");
+ if (!ctf_assert (fp, retstar))
+ goto assert_err;
+ retstar += 2; /* After the '*' */
- if (ctf_func_args (state->cds_fp, i, fi.ctc_argc, args) < 0)
- {
- err = "look up argument type";
- goto err;
- }
+ /* C is not good at search-and-replace. */
+ walk = new_bit;
+ memcpy (walk, bit, retstar - bit);
+ walk += (retstar - bit);
+ strcpy (walk, sym_name);
+ walk += strlen (sym_name);
+ strcpy (walk, retstar);
- for (j = 0; j < fi.ctc_argc; j++)
- {
- if ((bit = ctf_type_aname (state->cds_fp, args[j])) == NULL)
- {
- err = "look up argument type name";
- goto err;
- }
- str = str_append (str, bit);
- if ((j < fi.ctc_argc - 1) || (fi.ctc_flags & CTF_FUNC_VARARG))
- str = str_append (str, ", ");
free (bit);
+ bit = new_bit;
}
- if (fi.ctc_flags & CTF_FUNC_VARARG)
- str = str_append (str, "...");
- str = str_append (str, ")");
+ if (asprintf (&str, "Symbol 0x%lx: %s", (unsigned long) i, bit) < 0)
+ goto oom;
+ free (bit);
- free (args);
ctf_dump_append (state, str);
continue;
+ err:
+ ctf_err_warn (fp, 1, "Cannot %s dumping function type for "
+ "symbol 0x%li: %s", err, (unsigned long) i,
+ ctf_errmsg (ctf_errno (state->cds_fp)));
+ free (bit);
+ return -1; /* errno is set for us. */
+
oom:
- free (args);
- free (str);
+ free (bit);
return (ctf_set_errno (fp, errno));
- err:
- ctf_dprintf ("Cannot %s dumping function type for symbol 0x%li: %s\n",
- err, (unsigned long) i,
- ctf_errmsg (ctf_errno (state->cds_fp)));
- free (args);
- free (str);
+
+ assert_err:
+ free (bit);
return -1; /* errno is set for us. */
}
return 0;
diff --git a/libctf/ctf-types.c b/libctf/ctf-types.c
index 5500682..ddcca66 100644
--- a/libctf/ctf-types.c
+++ b/libctf/ctf-types.c
@@ -745,7 +745,51 @@ ctf_type_aname (ctf_file_t *fp, ctf_id_t type)
ctf_decl_sprintf (&cd, "[%u]", cdp->cd_n);
break;
case CTF_K_FUNCTION:
- ctf_decl_sprintf (&cd, "()");
+ {
+ size_t i;
+ ctf_funcinfo_t fi;
+ ctf_id_t *argv = NULL;
+
+ if (ctf_func_type_info (rfp, cdp->cd_type, &fi) < 0)
+ goto err; /* errno is set for us. */
+
+ if ((argv = calloc (fi.ctc_argc, sizeof (ctf_id_t *))) == NULL)
+ {
+ ctf_set_errno (rfp, errno);
+ goto err;
+ }
+
+ if (ctf_func_type_args (rfp, cdp->cd_type,
+ fi.ctc_argc, argv) < 0)
+ goto err; /* errno is set for us. */
+
+ ctf_decl_sprintf (&cd, "(*) (");
+ for (i = 0; i < fi.ctc_argc; i++)
+ {
+ char *arg = ctf_type_aname (rfp, argv[i]);
+
+ if (arg == NULL)
+ goto err; /* errno is set for us. */
+ ctf_decl_sprintf (&cd, "%s", arg);
+ free (arg);
+
+ if ((i < fi.ctc_argc - 1)
+ || (fi.ctc_flags & CTF_FUNC_VARARG))
+ ctf_decl_sprintf (&cd, ", ");
+ }
+
+ if (fi.ctc_flags & CTF_FUNC_VARARG)
+ ctf_decl_sprintf (&cd, "...");
+ ctf_decl_sprintf (&cd, ")");
+
+ free (argv);
+ break;
+
+ err:
+ free (argv);
+ ctf_decl_fini (&cd);
+ return NULL;
+ }
break;
case CTF_K_STRUCT:
case CTF_K_FORWARD: