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 <anchao@xiaomi.com>
This commit is contained in:
chao.an 2021-12-07 21:06:44 +08:00 committed by Xiang Xiao
parent d20bd62e08
commit d3a07ca26c

View File

@ -50,6 +50,7 @@
#include <nuttx/compiler.h>
#include <nuttx/streams.h>
#include <nuttx/allsyms.h>
#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 */