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:
parent
d20bd62e08
commit
d3a07ca26c
@ -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 */
|
||||
|
Loading…
Reference in New Issue
Block a user