X-Git-Url: https://git.libre-soc.org/?a=blobdiff_plain;f=libctf%2Fctf-subr.c;h=83572320f4cbb1c37e28481b3c0ee29cfd62a719;hb=2f6831b8066cd758e2f39c38503d2fa41608b9a7;hp=b897351b82330f817356229e8c08bc88df55ed9a;hpb=f5e73be11b24b6c4b7ecec5f762784c4bb40ec18;p=binutils-gdb.git diff --git a/libctf/ctf-subr.c b/libctf/ctf-subr.c index b897351b823..83572320f4c 100644 --- a/libctf/ctf-subr.c +++ b/libctf/ctf-subr.c @@ -1,5 +1,5 @@ /* Simple subrs. - Copyright (C) 2019 Free Software Foundation, Inc. + Copyright (C) 2019-2022 Free Software Foundation, Inc. This file is part of libctf. @@ -26,48 +26,12 @@ #include #include -static size_t _PAGESIZE _libctf_unused_; -int _libctf_version = CTF_VERSION; /* Library client version. */ -int _libctf_debug = 0; /* Debugging messages enabled. */ - -_libctf_malloc_ void * -ctf_data_alloc (size_t size) -{ - void *ret; - -#ifdef HAVE_MMAP - if (_PAGESIZE == 0) - _PAGESIZE = sysconf(_SC_PAGESIZE); - - if (size > _PAGESIZE) - { - ret = mmap (NULL, size, PROT_READ | PROT_WRITE, - MAP_PRIVATE | MAP_ANON, -1, 0); - if (ret == MAP_FAILED) - ret = NULL; - } - else - ret = calloc (1, size); -#else - ret = calloc (1, size); +#ifndef ENOTSUP +#define ENOTSUP ENOSYS #endif - return ret; -} -void -ctf_data_free (void *buf, size_t size _libctf_unused_) -{ -#ifdef HAVE_MMAP - /* Must be the same as the check in ctf_data_alloc(). */ - - if (size > _PAGESIZE) - (void) munmap (buf, size); - else - free (buf); -#else - free (buf); -#endif -} +int _libctf_version = CTF_VERSION; /* Library client version. */ +int _libctf_debug = 0; /* Debugging messages enabled. */ /* Private, read-only mmap from a file, with fallback to copying. @@ -105,29 +69,6 @@ ctf_munmap (void *buf, size_t length _libctf_unused_) #endif } -void -ctf_data_protect (void *buf _libctf_unused_, size_t size _libctf_unused_) -{ -#ifdef HAVE_MMAP - /* Must be the same as the check in ctf_data_alloc(). */ - - if (size > _PAGESIZE) - (void) mprotect (buf, size, PROT_READ); -#endif -} - -_libctf_malloc_ void * -ctf_alloc (size_t size) -{ - return (malloc (size)); -} - -void -ctf_free (void *buf) -{ - free (buf); -} - ssize_t ctf_pread (int fd, void *buf, ssize_t count, off_t offset) { @@ -185,12 +126,6 @@ ctf_pread (int fd, void *buf, ssize_t count, off_t offset) return acc; } -const char * -ctf_strerror (int err) -{ - return (const char *) (strerror (err)); -} - /* Set the CTF library client version to the specified version. If version is zero, we just return the default library version number. */ int @@ -246,7 +181,7 @@ int ctf_getdebug (void) _libctf_printflike_ (1, 2) void ctf_dprintf (const char *format, ...) { - if (_libctf_debug) + if (_libctf_unlikely_ (_libctf_debug)) { va_list alist; @@ -257,3 +192,155 @@ void ctf_dprintf (const char *format, ...) va_end (alist); } } + +/* This needs more attention to thread-safety later on. */ +static ctf_list_t open_errors; + +/* Errors and warnings. Report the warning or error to the list in FP (or the + open errors list if NULL): if ERR is nonzero it is the errno to report to the + debug stream instead of that recorded on fp. */ +_libctf_printflike_ (4, 5) +extern void +ctf_err_warn (ctf_dict_t *fp, int is_warning, int err, + 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); + + /* Include the error code only if there is one; if this is not a warning, + only use the error code if it was explicitly passed and is nonzero. + (Warnings may not have a meaningful error code, since the warning may not + lead to unwinding up to the user.) */ + if ((!is_warning && (err != 0 || (fp && ctf_errno (fp) != 0))) + || (is_warning && err != 0)) + ctf_dprintf ("%s: %s (%s)\n", is_warning ? _("error") : _("warning"), + cew->cew_text, err != 0 ? ctf_errmsg (err) + : ctf_errmsg (ctf_errno (fp))); + else + ctf_dprintf ("%s: %s\n", is_warning ? _("error") : _("warning"), + cew->cew_text); + + if (fp != NULL) + ctf_list_append (&fp->ctf_errs_warnings, cew); + else + ctf_list_append (&open_errors, cew); +} + +/* Move all the errors/warnings from an fp into the open_errors. */ +void +ctf_err_warn_to_open (ctf_dict_t *fp) +{ + ctf_list_splice (&open_errors, &fp->ctf_errs_warnings); +} + +/* 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. + + An fp of NULL returns CTF-open-time errors from the open_errors variable + above. + + The treatment of errors from this function itself is somewhat unusual: it + will often be called on an error path, so we don't want to overwrite the + ctf_errno unless we have no choice. So, like ctf_bufopen et al, this + function takes an errp pointer where errors are reported. The pointer is + optional: if not set, errors are reported via the fp (if non-NULL). Calls + with neither fp nor errp set are mildly problematic because there is no clear + way to report end-of-iteration: you just have to assume that a NULL return + means the end, and not an iterator error. */ + +char * +ctf_errwarning_next (ctf_dict_t *fp, ctf_next_t **it, int *is_warning, + int *errp) +{ + ctf_next_t *i = *it; + char *ret; + ctf_list_t *errlist; + ctf_err_warning_t *cew; + + if (fp) + errlist = &fp->ctf_errs_warnings; + else + errlist = &open_errors; + + if (!i) + { + if ((i = ctf_next_create ()) == NULL) + { + if (errp) + *errp = ENOMEM; + else if (fp) + 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) + { + if (errp) + *errp = ECTF_NEXT_WRONGFUN; + else if (fp) + ctf_set_errno (fp, ECTF_NEXT_WRONGFUN); + return NULL; + } + + if (fp != i->cu.ctn_fp) + { + if (errp) + *errp = ECTF_NEXT_WRONGFP; + else if (fp) + ctf_set_errno (fp, ECTF_NEXT_WRONGFP); + return NULL; + } + + cew = ctf_list_next (errlist); + + if (!cew) + { + ctf_next_destroy (i); + *it = NULL; + if (errp) + *errp = ECTF_NEXT_END; + else if (fp) + 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 (errlist, cew); + free (cew); + return ret; +} + +void +ctf_assert_fail_internal (ctf_dict_t *fp, const char *file, size_t line, + const char *exprstr) +{ + ctf_err_warn (fp, 0, ECTF_INTERNAL, _("%s: %lu: libctf assertion failed: %s"), + file, (long unsigned int) line, exprstr); + ctf_set_errno (fp, ECTF_INTERNAL); +}