From d3a07ca26c58e890e8bb73657e3ed32620aebd4c Mon Sep 17 00:00:00 2001 From: "chao.an" Date: Tue, 7 Dec 2021 21:06:44 +0800 Subject: [PATCH] libs/printf: add support for print symbol name Show a '%p' thing. A nuttx extension is that the '%p' is followed by an extra set of alphanumeric characters that are extended format specifiers. * - 'S' For symbolic direct pointers (or function descriptors) with offset * - 's' For symbolic direct pointers (or function descriptors) without offset printf("%ps %pS\n", ptr, ptr) will print: module_start module_start+0x0/0x62 Signed-off-by: chao.an --- libs/libc/stdio/lib_libvsprintf.c | 93 +++++++++++++++++++++++++------ 1 file changed, 77 insertions(+), 16 deletions(-) diff --git a/libs/libc/stdio/lib_libvsprintf.c b/libs/libc/stdio/lib_libvsprintf.c index 6e0fef0fd3..0c13d35800 100644 --- a/libs/libc/stdio/lib_libvsprintf.c +++ b/libs/libc/stdio/lib_libvsprintf.c @@ -50,6 +50,7 @@ #include #include +#include #include "lib_dtoa_engine.h" #include "lib_ultoa_invert.h" @@ -145,9 +146,34 @@ struct arg static const char g_nullstring[] = "(null)"; /**************************************************************************** - * Public Functions + * Private Function Prototypes ****************************************************************************/ +static int vsprintf_internal(FAR struct lib_outstream_s *stream, + FAR struct arg *arglist, int numargs, + FAR const IPTR char *fmt, va_list ap); + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +#ifdef CONFIG_ALLSYMS +static int sprintf_internal(FAR struct lib_outstream_s *stream, + FAR const IPTR char *fmt, ...) +{ + va_list ap; + int n; + + /* Then let vsprintf_internal do the real work */ + + va_start(ap, fmt); + n = vsprintf_internal(stream, NULL, 0, fmt, ap); + va_end(ap); + + return n; +} +#endif + static int vsprintf_internal(FAR struct lib_outstream_s *stream, FAR struct arg *arglist, int numargs, FAR const IPTR char *fmt, va_list ap) @@ -461,23 +487,58 @@ static int vsprintf_internal(FAR struct lib_outstream_s *stream, if (c == 'p') { - if (fmt_char(fmt) == 'V') - { - FAR struct va_format *vaf = va_arg(ap, void *); -#ifdef va_copy - va_list copy; + unsigned char sub_c = fmt_char(fmt); - va_copy(copy, *vaf->va); - vsprintf_internal(stream, NULL, 0, vaf->fmt, copy); - va_end(copy); -#else - vsprintf_internal(stream, NULL, 0, vaf->fmt, *vaf->va); -#endif - continue; - } - else + switch (sub_c) { - fmt_ungetc(fmt); + case 'V': + { + FAR struct va_format *vaf = va_arg(ap, void *); +#ifdef va_copy + va_list copy; + + va_copy(copy, *vaf->va); + vsprintf_internal(stream, NULL, 0, vaf->fmt, copy); + va_end(copy); +#else + vsprintf_internal(stream, NULL, 0, vaf->fmt, *vaf->va); +#endif + continue; + } +#ifdef CONFIG_ALLSYMS + + case 'S': + case 's': + { + FAR const struct symtab_s *symbol; + FAR void *addr = va_arg(ap, FAR void *); + size_t symbolsize; + + symbol = allsyms_findbyvalue(addr, &symbolsize); + if (symbol) + { + pnt = symbol->sym_name; + while (*pnt) + { + putc(*pnt++, stream); + } + + if (sub_c == 'S') + { + sprintf_internal(stream, "+%#x/%#x", + addr - symbol->sym_value, + symbolsize); + } + + continue; + } + } +#endif + + default: + { + fmt_ungetc(fmt); + } } /* Determine size of pointer and set flags accordingly */