diff options
author | Nick Alcock <nick.alcock@oracle.com> | 2025-01-13 11:29:26 +0000 |
---|---|---|
committer | Nick Alcock <nick.alcock@oracle.com> | 2025-02-28 15:12:02 +0000 |
commit | 4a7870a831cbcba4dad6f896d174a28b79d7318c (patch) | |
tree | 1d5151b42b14ff292649f1b1d9aa984eaa5a7309 /libctf/ctf-subr.c | |
parent | ac07bccf05468b089e23765e5be307054712a211 (diff) | |
download | binutils-4a7870a831cbcba4dad6f896d174a28b79d7318c.zip binutils-4a7870a831cbcba4dad6f896d174a28b79d7318c.tar.gz binutils-4a7870a831cbcba4dad6f896d174a28b79d7318c.tar.bz2 |
libctf: split up ctf-subr.c
This file is a bit of a grab-bag of dict-wide API functions like
ctf_set_open_errno or ctf_errwarning_next and portabilty functions and
wrappers like ctf_mmap or ctf_pread.
Split the latter out, and move other dict-wide functions that got
stuck in ctf-util.c (because it was so hard to tell the two files
apart) into ctf-api.c where they belong.
Diffstat (limited to 'libctf/ctf-subr.c')
-rw-r--r-- | libctf/ctf-subr.c | 383 |
1 files changed, 0 insertions, 383 deletions
diff --git a/libctf/ctf-subr.c b/libctf/ctf-subr.c deleted file mode 100644 index 12f8469..0000000 --- a/libctf/ctf-subr.c +++ /dev/null @@ -1,383 +0,0 @@ -/* Simple subrs. - Copyright (C) 2019-2025 Free Software Foundation, Inc. - - This file is part of libctf. - - libctf is free software; you can redistribute it and/or modify it under - the terms of the GNU General Public License as published by the Free - Software Foundation; either version 3, or (at your option) any later - version. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - See the GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; see the file COPYING. If not see - <http://www.gnu.org/licenses/>. */ - -#include <ctf-impl.h> -#ifdef HAVE_MMAP -#include <sys/mman.h> -#endif -#include <sys/types.h> -#include <stdarg.h> -#include <string.h> -#include <unistd.h> - -#ifndef ENOTSUP -#define ENOTSUP ENOSYS -#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. - - No handling of page-offset issues at all: the caller must allow for that. */ - -_libctf_malloc_ void * -ctf_mmap (size_t length, size_t offset, int fd) -{ - void *data; - -#ifdef HAVE_MMAP - data = mmap (NULL, length, PROT_READ, MAP_PRIVATE, fd, offset); - if (data == MAP_FAILED) - data = NULL; -#else - if ((data = malloc (length)) != NULL) - { - if (ctf_pread (fd, data, length, offset) <= 0) - { - free (data); - data = NULL; - } - } -#endif - return data; -} - -void -ctf_munmap (void *buf, size_t length _libctf_unused_) -{ -#ifdef HAVE_MMAP - (void) munmap (buf, length); -#else - free (buf); -#endif -} - -ssize_t -ctf_pread (int fd, void *buf, ssize_t count, off_t offset) -{ - ssize_t len; - size_t acc = 0; - char *data = (char *) buf; - -#ifdef HAVE_PREAD - while (count > 0) - { - errno = 0; - if (((len = pread (fd, data, count, offset)) < 0) && - errno != EINTR) - return len; - if (errno == EINTR) - continue; - - acc += len; - if (len == 0) /* EOF. */ - return acc; - - count -= len; - offset += len; - data += len; - } - return acc; -#else - off_t orig_off; - - if ((orig_off = lseek (fd, 0, SEEK_CUR)) < 0) - return -1; - if ((lseek (fd, offset, SEEK_SET)) < 0) - return -1; - - while (count > 0) - { - errno = 0; - if (((len = read (fd, data, count)) < 0) && - errno != EINTR) - return len; - if (errno == EINTR) - continue; - - acc += len; - if (len == 0) /* EOF. */ - break; - - count -= len; - data += len; - } - if ((lseek (fd, orig_off, SEEK_SET)) < 0) - return -1; /* offset is smashed. */ -#endif - - return acc; -} - -/* Set the CTF library client version to the specified version. If version is - zero, we just return the default library version number. */ -int -ctf_version (int version) -{ - if (version < 0) - { - errno = EINVAL; - return -1; - } - - if (version > 0) - { - /* Dynamic version switching is not presently supported. */ - if (version != CTF_VERSION) - { - errno = ENOTSUP; - return -1; - } - ctf_dprintf ("ctf_version: client using version %d\n", version); - _libctf_version = version; - } - - return _libctf_version; -} - -/* Get and set CTF dict-wide flags. We are fairly strict about returning - errors here, to make it easier to determine programmatically which flags are - valid. */ - -int -ctf_dict_set_flag (ctf_dict_t *fp, uint64_t flag, int set) -{ - if (set < 0 || set > 1) - return (ctf_set_errno (fp, ECTF_BADFLAG)); - - switch (flag) - { - case CTF_STRICT_NO_DUP_ENUMERATORS: - if (set) - fp->ctf_flags |= LCTF_STRICT_NO_DUP_ENUMERATORS; - else - fp->ctf_flags &= ~LCTF_STRICT_NO_DUP_ENUMERATORS; - break; - default: - return (ctf_set_errno (fp, ECTF_BADFLAG)); - } - return 0; -} - -int -ctf_dict_get_flag (ctf_dict_t *fp, uint64_t flag) -{ - switch (flag) - { - case CTF_STRICT_NO_DUP_ENUMERATORS: - return (fp->ctf_flags & LCTF_STRICT_NO_DUP_ENUMERATORS) != 0; - default: - return (ctf_set_errno (fp, ECTF_BADFLAG)); - } - return 0; -} - -void -libctf_init_debug (void) -{ - static int inited; - if (!inited) - { - _libctf_debug = getenv ("LIBCTF_DEBUG") != NULL; - inited = 1; - } -} - -void ctf_setdebug (int debug) -{ - /* Ensure that libctf_init_debug() has been called, so that we don't get our - debugging-on-or-off smashed by the next call. */ - - libctf_init_debug(); - _libctf_debug = debug; - ctf_dprintf ("CTF debugging set to %i\n", debug); -} - -int ctf_getdebug (void) -{ - return _libctf_debug; -} - -_libctf_printflike_ (1, 2) -void ctf_dprintf (const char *format, ...) -{ - if (_libctf_unlikely_ (_libctf_debug)) - { - va_list alist; - - va_start (alist, format); - fflush (stdout); - (void) fputs ("libctf DEBUG: ", stderr); - (void) vfprintf (stderr, format, alist); - 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 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 ? _("warning") : _("error"), - cew->cew_text, err != 0 ? ctf_errmsg (err) - : ctf_errmsg (ctf_errno (fp))); - else - ctf_dprintf ("%s: %s\n", is_warning ? _("warning") : _("error"), - 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_set_errno (fp, ECTF_INTERNAL); - ctf_err_warn (fp, 0, 0, _("%s: %lu: libctf assertion failed: %s"), - file, (long unsigned int) line, exprstr); -} |