+2020-07-22 Nick Alcock <nick.alcock@oracle.com>
+
+ * objdump.c (ctf_archive_member): Print CTF errors and warnings.
+ * readelf.c (dump_ctf_archive_member): Likewise.
+
2020-07-22 Nick Clifton <nickc@redhat.com>
* readelf.c (parse_args): Silence potential warnings about a
"Function objects", "Variables", "Types", "Strings",
""};
const char **thing;
+ ctf_next_t *it = NULL;
+ char *errtext;
+ int is_warning;
size_t i;
/* Only print out the name of non-default-named archive members.
break;
}
}
+
+ /* Dump accumulated errors and warnings. */
+ while ((errtext = ctf_errwarning_next (ctf, &it, &is_warning)) != NULL)
+ {
+ non_fatal (_("%s: `%s'"), is_warning ? _("warning"): _("error"),
+ errtext);
+ free (errtext);
+ }
+ if (ctf_errno (ctf) != ECTF_NEXT_END)
+ {
+ non_fatal (_("CTF error: cannot get CTF errors: `%s'"),
+ ctf_errmsg (ctf_errno (ctf)));
+ }
+
return 0;
}
"Function objects", "Variables", "Types", "Strings",
""};
const char **thing;
+ ctf_next_t *it = NULL;
+ char *errtext;
+ int is_warning;
size_t i;
+ int err = 0;
/* Only print out the name of non-default-named archive members.
The name .ctf appears everywhere, even for things that aren't
{
error (_("Iteration failed: %s, %s\n"), *thing,
ctf_errmsg (ctf_errno (ctf)));
- return 1;
+ err = 1;
+ goto out;
}
}
- return 0;
+
+ out:
+ /* Dump accumulated errors and warnings. */
+ while ((errtext = ctf_errwarning_next (ctf, &it, &is_warning)) != NULL)
+ {
+ error (_("%s: `%s'\n"), is_warning ? _("warning"): _("error"),
+ errtext);
+ free (errtext);
+ }
+ if (ctf_errno (ctf) != ECTF_NEXT_END)
+ {
+ error (_("CTF error: cannot get CTF errors: `%s'\n"),
+ ctf_errmsg (ctf_errno (ctf)));
+ }
+ return err;
}
static bfd_boolean
+2020-07-22 Nick Alcock <nick.alcock@oracle.com>
+
+ * ctf-api.h (ECTF_INTERNAL): Adjust error text.
+ (ctf_errwarning_next): New.
+
2020-07-22 Nick Alcock <nick.alcock@oracle.com>
* ctf-api.h (ECTF_FLAGS): New.
ECTF_DUMPSECTUNKNOWN, /* Unknown section number in dump. */
ECTF_DUMPSECTCHANGED, /* Section changed in middle of dump. */
ECTF_NOTYET, /* Feature not yet implemented. */
- ECTF_INTERNAL, /* Internal error in link. */
+ ECTF_INTERNAL, /* Internal error: assertion failure. */
ECTF_NONREPRESENTABLE, /* Type not representable in CTF. */
ECTF_NEXT_END, /* End of iteration. */
ECTF_NEXT_WRONGFUN, /* Wrong iteration function called. */
ctf_sect_names_t sect, ctf_dump_decorate_f *,
void *arg);
+/* Error-warning reporting: an 'iterator' that returns errors and warnings from
+ the error/warning list, in order of emission. Errors and warnings are popped
+ after return: the caller must free the returned error-text pointer. */
+extern char *ctf_errwarning_next (ctf_file_t *, ctf_next_t **,
+ int *is_warning);
+
extern ctf_id_t ctf_add_array (ctf_file_t *, uint32_t,
const ctf_arinfo_t *);
extern ctf_id_t ctf_add_const (ctf_file_t *, uint32_t, ctf_id_t);
+2020-07-22 Nick Alcock <nick.alcock@oracle.com>
+
+ * ldlang.c (lang_ctf_errs_warnings): New, print CTF errors
+ and warnings. Assert when libctf asserts.
+ (lang_merge_ctf): Call it.
+ (land_write_ctf): Likewise.
+
2020-07-22 H.J. Lu <hongjiu.lu@intel.com>
PR ld/26262
ctf_close (errfile->the_ctf);
}
+/* Emit CTF errors and warnings. */
+static void
+lang_ctf_errs_warnings (ctf_file_t *fp)
+{
+ ctf_next_t *i = NULL;
+ char *text;
+ int is_warning;
+
+ while ((text = ctf_errwarning_next (fp, &i, &is_warning)) != NULL)
+ {
+ einfo (_("%s: `%s'\n"), is_warning ? _("CTF warning"): _("CTF error"),
+ text);
+ free (text);
+ }
+ if (ctf_errno (fp) != ECTF_NEXT_END)
+ {
+ einfo (_("CTF error: cannot get CTF errors: `%s'\n"),
+ ctf_errmsg (ctf_errno (fp)));
+ }
+
+ ASSERT (ctf_errno (fp) != ECTF_INTERNAL);
+}
+
/* Merge together CTF sections. After this, only the symtab-dependent
function and data object sections need adjustment. */
output_sect->flags |= SEC_EXCLUDE;
}
}
+ lang_ctf_errs_warnings (ctf_output);
}
/* Let the emulation examine the symbol table and strtab to help it optimize the
output_sect->size = 0;
output_sect->flags |= SEC_EXCLUDE;
}
+
+ lang_ctf_errs_warnings (ctf_output);
}
/* This also closes every CTF input file used in the link. */
+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.
+ (ctf_err_warn): New prototype.
+ (ctf_assert_fail_internal): Likewise.
+ * ctf-inlines.h (ctf_assert_internal): Likewise.
+ * ctf-open.c (ctf_file_close): Free ctf_errs_warnings.
+ * ctf-create.c (ctf_serialize): Copy it on serialization.
+ * ctf-subr.c (ctf_err_warn): New, add an error/warning.
+ (ctf_errwarning_next): New iterator, free and pass back
+ errors/warnings in succession.
+ * libctf.ver (ctf_errwarning_next): Add.
+
2020-07-22 Egeyar Bagcioglu <egeyar.bagcioglu@oracle.com>
* ctf-types.c (ctf_variable_iter): Fix error return.
nfp->ctf_ptrtab_len = fp->ctf_ptrtab_len;
nfp->ctf_link_inputs = fp->ctf_link_inputs;
nfp->ctf_link_outputs = fp->ctf_link_outputs;
+ nfp->ctf_errs_warnings = fp->ctf_errs_warnings;
nfp->ctf_str_prov_offset = fp->ctf_str_prov_offset;
nfp->ctf_syn_ext_strtab = fp->ctf_syn_ext_strtab;
nfp->ctf_link_cu_mapping = fp->ctf_link_cu_mapping;
fp->ctf_str_atoms = NULL;
fp->ctf_prov_strtab = NULL;
memset (&fp->ctf_dtdefs, 0, sizeof (ctf_list_t));
+ memset (&fp->ctf_errs_warnings, 0, sizeof (ctf_list_t));
fp->ctf_add_processing = NULL;
fp->ctf_ptrtab = NULL;
fp->ctf_link_inputs = NULL;
#endif
+#define ctf_assert(fp, expr) \
+ _libctf_unlikely_ (ctf_assert_internal (fp, __FILE__, __LINE__, \
+ #expr, !!(expr)))
+
/* libctf in-memory state. */
typedef struct ctf_fixed_hash ctf_hash_t; /* Private to ctf-hash.c. */
ctf_dtdef_t *ctb_dtd; /* CTF dynamic type definition (if any). */
} ctf_bundle_t;
+typedef struct ctf_err_warning
+{
+ ctf_list_t cew_list; /* List forward/back pointers. */
+ int cew_is_warning; /* 1 if warning, 0 if error. */
+ char *cew_text; /* Error/warning text. */
+} ctf_err_warning_t;
+
/* Atoms associate strings with a list of the CTF items that reference that
string, so that ctf_update() can instantiate all the strings using the
ctf_str_atoms and then reassociate them with the real string later.
unsigned long ctf_snapshots; /* ctf_snapshot() plus ctf_update() count. */
unsigned long ctf_snapshot_lu; /* ctf_snapshot() call count at last update. */
ctf_archive_t *ctf_archive; /* Archive this ctf_file_t came from. */
+ ctf_list_t ctf_errs_warnings; /* CTF errors and warnings. */
ctf_dynhash_t *ctf_link_inputs; /* Inputs to this link. */
ctf_dynhash_t *ctf_link_outputs; /* Additional outputs from this link. */
ctf_dynhash_t *ctf_link_type_mapping; /* Map input types to output types. */
extern void ctf_dprintf (const char *, ...);
extern void libctf_init_debug (void);
+_libctf_printflike_ (3, 4)
+extern void ctf_err_warn (ctf_file_t *, int is_warning, const char *, ...);
+extern void ctf_assert_fail_internal (ctf_file_t *, const char *,
+ size_t, const char *);
+
extern Elf64_Sym *ctf_sym_to_elf64 (const Elf32_Sym *src, Elf64_Sym *dst);
extern const char *ctf_lookup_symbol_name (ctf_file_t *fp, unsigned long symidx);
return ctf_dynset_insert (h, (void *) k);
}
+static inline int
+ctf_assert_internal (ctf_file_t *fp, const char *file, size_t line,
+ const char *exprstr, int expr)
+{
+ if (_libctf_unlikely_ (!expr))
+ ctf_assert_fail_internal (fp, file, line, exprstr);
+
+ return expr;
+}
+
#ifdef __cplusplus
}
#endif
{
ctf_dtdef_t *dtd, *ntd;
ctf_dvdef_t *dvd, *nvd;
+ ctf_err_warning_t *err, *nerr;
if (fp == NULL)
return; /* Allow ctf_file_close(NULL) to simplify caller code. */
ctf_dynhash_destroy (fp->ctf_link_cu_mapping);
ctf_dynhash_destroy (fp->ctf_add_processing);
+ for (err = ctf_list_next (&fp->ctf_errs_warnings); err != NULL; err = nerr)
+ {
+ nerr = ctf_list_next (err);
+ ctf_list_delete (&fp->ctf_errs_warnings, err);
+ free (err->cew_text);
+ free (err);
+ }
+
free (fp->ctf_sxlate);
free (fp->ctf_txlate);
free (fp->ctf_ptrtab);
va_end (alist);
}
}
+
+/* Errors and warnings. */
+_libctf_printflike_ (3, 4)
+extern void
+ctf_err_warn (ctf_file_t *fp, int is_warning, const char *format, ...)
+{
+ va_list alist;
+ ctf_err_warning_t *cew;
+
+ /* Don't bother reporting errors here: we can't do much about them if they
+ happen. If we're so short of memory that a tiny malloc doesn't work, a
+ vfprintf isn't going to work either and the caller will have to rely on the
+ ENOMEM return they'll be getting in short order anyway. */
+
+ if ((cew = malloc (sizeof (ctf_err_warning_t))) == NULL)
+ return;
+
+ cew->cew_is_warning = is_warning;
+ va_start (alist, format);
+ if (vasprintf (&cew->cew_text, format, alist) < 0)
+ {
+ free (cew);
+ va_end (alist);
+ return;
+ }
+ va_end (alist);
+
+ ctf_dprintf ("%s: %s\n", is_warning ? "error" : "warning", cew->cew_text);
+
+ ctf_list_append (&fp->ctf_errs_warnings, cew);
+}
+
+/* Error-warning reporting: an 'iterator' that returns errors and warnings from
+ the error/warning list, in order of emission. Errors and warnings are popped
+ after return: the caller must free the returned error-text pointer. */
+char *
+ctf_errwarning_next (ctf_file_t *fp, ctf_next_t **it, int *is_warning)
+{
+ ctf_next_t *i = *it;
+ char *ret;
+ ctf_err_warning_t *cew;
+
+ if (!i)
+ {
+ if ((i = ctf_next_create ()) == NULL)
+ {
+ ctf_set_errno (fp, ENOMEM);
+ return NULL;
+ }
+
+ i->cu.ctn_fp = fp;
+ i->ctn_iter_fun = (void (*) (void)) ctf_errwarning_next;
+ *it = i;
+ }
+
+ if ((void (*) (void)) ctf_errwarning_next != i->ctn_iter_fun)
+ {
+ ctf_set_errno (fp, ECTF_NEXT_WRONGFUN);
+ return NULL;
+ }
+
+ if (fp != i->cu.ctn_fp)
+ {
+ ctf_set_errno (fp, ECTF_NEXT_WRONGFP);
+ return NULL;
+ }
+
+ cew = ctf_list_next (&fp->ctf_errs_warnings);
+
+ if (!cew)
+ {
+ ctf_next_destroy (i);
+ *it = NULL;
+ ctf_set_errno (fp, ECTF_NEXT_END);
+ return NULL;
+ }
+
+ if (is_warning)
+ *is_warning = cew->cew_is_warning;
+ ret = cew->cew_text;
+ ctf_list_delete (&fp->ctf_errs_warnings, cew);
+ free (cew);
+ return ret;
+}
+
+void
+ctf_assert_fail_internal (ctf_file_t *fp, const char *file, size_t line,
+ const char *exprstr)
+{
+ ctf_err_warn (fp, 0, "%s: %lu: libctf assertion failed: %s", file,
+ (long unsigned int) line, exprstr);
+ ctf_set_errno (fp, ECTF_INTERNAL);
+}
ctf_setdebug;
ctf_getdebug;
+ ctf_errwarning_next;
/* Not yet part of the stable API. */