mirror of
https://github.com/apache/nuttx.git
synced 2026-05-31 14:27:37 +08:00
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:
@@ -50,6 +50,7 @@
|
|||||||
|
|
||||||
#include <nuttx/compiler.h>
|
#include <nuttx/compiler.h>
|
||||||
#include <nuttx/streams.h>
|
#include <nuttx/streams.h>
|
||||||
|
#include <nuttx/allsyms.h>
|
||||||
|
|
||||||
#include "lib_dtoa_engine.h"
|
#include "lib_dtoa_engine.h"
|
||||||
#include "lib_ultoa_invert.h"
|
#include "lib_ultoa_invert.h"
|
||||||
@@ -145,9 +146,34 @@ struct arg
|
|||||||
static const char g_nullstring[] = "(null)";
|
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,
|
static int vsprintf_internal(FAR struct lib_outstream_s *stream,
|
||||||
FAR struct arg *arglist, int numargs,
|
FAR struct arg *arglist, int numargs,
|
||||||
FAR const IPTR char *fmt, va_list ap)
|
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 (c == 'p')
|
||||||
{
|
{
|
||||||
if (fmt_char(fmt) == 'V')
|
unsigned char sub_c = fmt_char(fmt);
|
||||||
{
|
|
||||||
FAR struct va_format *vaf = va_arg(ap, void *);
|
|
||||||
#ifdef va_copy
|
|
||||||
va_list copy;
|
|
||||||
|
|
||||||
va_copy(copy, *vaf->va);
|
switch (sub_c)
|
||||||
vsprintf_internal(stream, NULL, 0, vaf->fmt, copy);
|
|
||||||
va_end(copy);
|
|
||||||
#else
|
|
||||||
vsprintf_internal(stream, NULL, 0, vaf->fmt, *vaf->va);
|
|
||||||
#endif
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
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 */
|
/* Determine size of pointer and set flags accordingly */
|
||||||
|
|||||||
Reference in New Issue
Block a user