git: 5dff273d680a - main - uexterr_gettext(3): support dynamic kernel categories
Brooks Davis <[email protected]> Mon, 03 Aug 2026 21:44:07 +0000
| Newsgroups | gmane.os.freebsd.devel.cvs.src |
|---|---|
| Message-ID | <6a710ba7.3cbc0.79d9e807__49839.5272925094$1785793638$gmane$org@gitrepo.freebsd.org> |
The branch main has been updated by brooks: URL: https://cgit.FreeBSD.org/src/commit/?id=5dff273d680ab848c62ca50efacb19f199217ab7 commit 5dff273d680ab848c62ca50efacb19f199217ab7 Author: Brooks Davis <[email protected]> AuthorDate: 2026-08-03 16:50:26 +0000 Commit: Brooks Davis <[email protected]> CommitDate: 2026-08-03 21:43:23 +0000 uexterr_gettext(3): support dynamic kernel categories Add an uncached sysctl based implementation which retrieves individual categories. A cache would be an obvious extension should this optional feature that can only be enabled by an environmental varible have a noticable performance impact in a case that matters. Reviewed by: kib Sponsored by: Innovate UK Differential Revision: https://reviews.freebsd.org/D58238 --- lib/libc/gen/uexterr_format.c | 68 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 64 insertions(+), 4 deletions(-) diff --git a/lib/libc/gen/uexterr_format.c b/lib/libc/gen/uexterr_format.c index df93ae1447cd..99ae85715f43 100644 --- a/lib/libc/gen/uexterr_format.c +++ b/lib/libc/gen/uexterr_format.c @@ -11,20 +11,75 @@ #include <sys/param.h> #include <sys/exterr_cat.h> #include <sys/exterrvar.h> +#include <sys/sysctl.h> #include <exterr.h> +#include <pthread.h> #include <stdbool.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> +#include "libc_private.h" + static const char * const cat_to_filenames[] = { #include "exterr_cat_filenames.h" }; +_Thread_local char filename_buf[128]; + +#define MIB_SIZE 4 +static int mib_template[MIB_SIZE]; +pthread_once_t mib_template_once_control = PTHREAD_ONCE_INIT; + +static void +mib_template_init(void) +{ + size_t len; + + len = nitems(mib_template); + (void)sysctlnametomib("kern.exterr.categories", mib_template, &len); + /* failure handled in kern_dynamic_cat_to_filename() */ +} + +static const char * +kern_dynamic_cat_to_filename(int category) +{ + int mib[MIB_SIZE]; + size_t len; + + if (_once(&mib_template_once_control, mib_template_init) != 0) + return (NULL); + if (__predict_false(mib_template[0] != CTL_KERN)) { + filename_buf[0] = '\0'; + return (filename_buf); + } + + memcpy(mib, mib_template, MIB_SIZE); + mib[MIB_SIZE - 1] = category; + len = sizeof(filename_buf); + if (sysctl(mib, nitems(mib), filename_buf, &len, NULL, 0) != 0) + return (NULL); + return (filename_buf); +} + +static const char * +cat_to_file_prefix(int category) +{ + switch (EXTERR_CAT_SRC(category)) { + case EXTERR_CAT_SRC_KERN_STATIC: + case EXTERR_CAT_SRC_KERN_DYNAMIC: + return ("sys/"); + default: + return (""); + } +} + static const char * cat_to_filename(int category) { + const char *path; + switch (EXTERR_CAT_SRC(category)) { case EXTERR_CAT_SRC_KERN_STATIC: if (category < 0 || category >= nitems(cat_to_filenames) || @@ -33,7 +88,10 @@ cat_to_filename(int category) return (cat_to_filenames[category]); case EXTERR_CAT_SRC_KERN_DYNAMIC: - return ("unknown:kern"); + path = kern_dynamic_cat_to_filename(EXTERR_CAT(category)); + if (path == NULL) + return ("unknown:kern"); + return (path); case EXTERR_CAT_SRC_USER: return ("unknown:user"); @@ -97,16 +155,18 @@ __uexterr_format(const struct uexterror *ue, char *buf, size_t bufsz) if (exterror_verbose > EXTERR_VERBOSE_DEFAULT || !has_msg) { char lbuf[128]; -#define SRC_FMT "(src sys/%s:%u)" +#define SRC_FMT "(src %s%s:%u)" if (exterror_verbose == EXTERR_VERBOSE_ALLOW_BRIEF) { snprintf(lbuf, sizeof(lbuf), SRC_FMT, + cat_to_file_prefix(ue->cat), cat_to_filename(ue->cat), ue->src_line); } else if (!has_msg || exterror_verbose == EXTERR_VERBOSE_ALLOW_FULL) { snprintf(lbuf, sizeof(lbuf), "errno %d category %u " SRC_FMT " p1 %#jx p2 %#jx", - ue->error, ue->cat, cat_to_filename(ue->cat), - ue->src_line, (uintmax_t)ue->p1, (uintmax_t)ue->p2); + ue->error, ue->cat, cat_to_file_prefix(ue->cat), + cat_to_filename(ue->cat), ue->src_line, + (uintmax_t)ue->p1, (uintmax_t)ue->p2); } #undef SRC_FMT if (has_msg)