diff options
Diffstat (limited to 'libctf')
-rw-r--r-- | libctf/ChangeLog | 15 | ||||
-rw-r--r-- | libctf/ctf-create.c | 2 | ||||
-rw-r--r-- | libctf/ctf-impl.h | 17 | ||||
-rw-r--r-- | libctf/ctf-inlines.h | 10 | ||||
-rw-r--r-- | libctf/ctf-open.c | 9 | ||||
-rw-r--r-- | libctf/ctf-subr.c | 93 | ||||
-rw-r--r-- | libctf/libctf.ver | 1 |
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. */ |