aboutsummaryrefslogtreecommitdiff
path: root/libctf
diff options
context:
space:
mode:
Diffstat (limited to 'libctf')
-rw-r--r--libctf/ChangeLog15
-rw-r--r--libctf/ctf-create.c2
-rw-r--r--libctf/ctf-impl.h17
-rw-r--r--libctf/ctf-inlines.h10
-rw-r--r--libctf/ctf-open.c9
-rw-r--r--libctf/ctf-subr.c93
-rw-r--r--libctf/libctf.ver1
7 files changed, 147 insertions, 0 deletions
diff --git a/libctf/ChangeLog b/libctf/ChangeLog
index f3ac4cc..114d4e6 100644
--- a/libctf/ChangeLog
+++ b/libctf/ChangeLog
@@ -1,3 +1,18 @@
+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.
diff --git a/libctf/ctf-create.c b/libctf/ctf-create.c
index d50367d..a538b2d 100644
--- a/libctf/ctf-create.c
+++ b/libctf/ctf-create.c
@@ -534,6 +534,7 @@ ctf_serialize (ctf_file_t *fp)
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;
@@ -556,6 +557,7 @@ ctf_serialize (ctf_file_t *fp)
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;
diff --git a/libctf/ctf-impl.h b/libctf/ctf-impl.h
index eea5204..47a3927 100644
--- a/libctf/ctf-impl.h
+++ b/libctf/ctf-impl.h
@@ -70,6 +70,10 @@ extern "C"
#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. */
@@ -195,6 +199,13 @@ typedef struct ctf_bundle
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.
@@ -297,6 +308,7 @@ struct ctf_file
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. */
@@ -543,6 +555,11 @@ _libctf_printflike_ (1, 2)
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);
diff --git a/libctf/ctf-inlines.h b/libctf/ctf-inlines.h
index a35b6cd..affc9f9 100644
--- a/libctf/ctf-inlines.h
+++ b/libctf/ctf-inlines.h
@@ -80,6 +80,16 @@ ctf_dynset_cinsert (ctf_dynset_t *h, const void *k)
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
diff --git a/libctf/ctf-open.c b/libctf/ctf-open.c
index f8eeaab..24899f0 100644
--- a/libctf/ctf-open.c
+++ b/libctf/ctf-open.c
@@ -1644,6 +1644,7 @@ ctf_file_close (ctf_file_t *fp)
{
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. */
@@ -1710,6 +1711,14 @@ ctf_file_close (ctf_file_t *fp)
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);
diff --git a/libctf/ctf-subr.c b/libctf/ctf-subr.c
index a5cde9d..0b49ae9 100644
--- a/libctf/ctf-subr.c
+++ b/libctf/ctf-subr.c
@@ -194,3 +194,96 @@ void ctf_dprintf (const char *format, ...)
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);
+}
diff --git a/libctf/libctf.ver b/libctf/libctf.ver
index e99f890..f1c9b2b 100644
--- a/libctf/libctf.ver
+++ b/libctf/libctf.ver
@@ -154,6 +154,7 @@ LIBCTF_1.0 {
ctf_setdebug;
ctf_getdebug;
+ ctf_errwarning_next;
/* Not yet part of the stable API. */