Understanding the operation and caching of the tool can be somewhat challenging without a debugger. Add inline debugging information with the --inline-debug command, which adds highlighted tags to the --debug output with information about cache states etc. Signed-off-by: Sami Tolvanen <samitolvanen@xxxxxxxxxx> --- tools/gendwarfksyms/gendwarfksyms.c | 3 +++ tools/gendwarfksyms/gendwarfksyms.h | 29 +++++++++++++++++++++++++++++ tools/gendwarfksyms/types.c | 14 ++++++++++++++ 3 files changed, 46 insertions(+) diff --git a/tools/gendwarfksyms/gendwarfksyms.c b/tools/gendwarfksyms/gendwarfksyms.c index 7095f0ecccab..acf4b44238e2 100644 --- a/tools/gendwarfksyms/gendwarfksyms.c +++ b/tools/gendwarfksyms/gendwarfksyms.c @@ -15,6 +15,8 @@ /* Print type descriptions and debugging output to stderr */ bool debug; +/* Print inline debugging information to stderr (with --debug) */ +bool inline_debug; /* Don't use caching */ bool no_cache; /* Don't pretty-print (with --debug) */ @@ -25,6 +27,7 @@ static const struct { bool *flag; } options[] = { { "--debug", &debug }, + { "--inline-debug", &inline_debug }, { "--no-cache", &no_cache }, { "--no-pretty-print", &no_pretty_print }, }; diff --git a/tools/gendwarfksyms/gendwarfksyms.h b/tools/gendwarfksyms/gendwarfksyms.h index 568f3727017e..34d1be3cfb7f 100644 --- a/tools/gendwarfksyms/gendwarfksyms.h +++ b/tools/gendwarfksyms/gendwarfksyms.h @@ -18,6 +18,7 @@ * Options -- in gendwarfksyms.c */ extern bool debug; +extern bool inline_debug; extern bool no_cache; extern bool no_pretty_print; @@ -38,6 +39,18 @@ extern bool no_pretty_print; #define warn(format, ...) __println("warning: ", format, ##__VA_ARGS__) #define error(format, ...) __println("error: ", format, ##__VA_ARGS__) +#define __inline_debug(color, format, ...) \ + do { \ + if (debug && inline_debug) \ + fprintf(stderr, \ + "\033[" #color "m<" format ">\033[39m", \ + __VA_ARGS__); \ + } while (0) + +#define inline_debug_r(format, ...) __inline_debug(91, format, __VA_ARGS__) +#define inline_debug_g(format, ...) __inline_debug(92, format, __VA_ARGS__) +#define inline_debug_b(format, ...) __inline_debug(94, format, __VA_ARGS__) + /* * Error handling helpers */ @@ -51,6 +64,9 @@ extern bool no_pretty_print; __res; \ }) +/* + * DWARF helpers + */ /* Consistent aliases (DW_TAG_<type>_type) for DWARF tags */ #define DW_TAG_enumerator_type DW_TAG_enumerator #define DW_TAG_formal_parameter_type DW_TAG_formal_parameter @@ -97,6 +113,19 @@ struct cached_item { enum cached_die_state { INCOMPLETE, UNEXPANDED, COMPLETE }; +static inline const char *cache_state_name(enum cached_die_state state) +{ + switch (state) { + default: + case INCOMPLETE: + return "INCOMPLETE"; + case UNEXPANDED: + return "UNEXPANDED"; + case COMPLETE: + return "COMPLETE"; + } +} + struct cached_die { enum cached_die_state state; uintptr_t addr; diff --git a/tools/gendwarfksyms/types.c b/tools/gendwarfksyms/types.c index da3aa2ad9f57..694b33cdd606 100644 --- a/tools/gendwarfksyms/types.c +++ b/tools/gendwarfksyms/types.c @@ -97,6 +97,7 @@ static int process(struct state *state, struct cached_die *cache, const char *s) fputs(s, stderr); state->crc = partial_crc32(s, state->crc); + inline_debug_r("cache %p string '%s'", cache, s); return cache_add_string(cache, s); } @@ -456,6 +457,8 @@ static int process_cached(struct state *state, struct cached_die *cache, while (ci) { switch (ci->type) { case STRING: + inline_debug_b("cache %p STRING '%s'", cache, + ci->data.str); check(process(state, NULL, ci->data.str)); break; case LINEBREAK: @@ -468,6 +471,8 @@ static int process_cached(struct state *state, struct cached_die *cache, error("dwarf_die_addr_die failed"); return -1; } + inline_debug_b("cache %p DIE addr %lx tag %d", cache, + ci->data.addr, dwarf_tag(&child)); check(process_type(state, NULL, &child)); break; default: @@ -561,6 +566,9 @@ static int process_type(struct state *state, struct cached_die *parent, check(cache_get(die, want_state, &cache)); if (cache->state == want_state) { + inline_debug_g("cached addr %p tag %d -- %s", die->addr, + tag, cache_state_name(cache->state)); + if (want_state == COMPLETE && is_expanded_type(tag)) check(cache_mark_expanded(die)); @@ -572,6 +580,9 @@ static int process_type(struct state *state, struct cached_die *parent, } } + inline_debug_g("addr %p tag %d -- INCOMPLETE -> %s", die->addr, tag, + cache_state_name(want_state)); + switch (tag) { /* Type modifiers */ PROCESS_TYPE(atomic) @@ -608,6 +619,9 @@ static int process_type(struct state *state, struct cached_die *parent, } if (!no_cache) { + inline_debug_r("parent %p cache %p die addr %p tag %d", parent, + cache, die->addr, tag); + /* Update cache state and append to the parent (if any) */ cache->state = want_state; check(cache_add_die(parent, die)); -- 2.45.2.627.g7a2c4fd464-goog