mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-12-27 12:21:22 -05:00
gendwarfksyms: Expand subroutine_type
Add support for expanding DW_TAG_subroutine_type and the parameters
in DW_TAG_formal_parameter. Use this to also expand subprograms.
Example output with --dump-dies:
subprogram (
formal_parameter pointer_type {
const_type {
base_type char byte_size(1) encoding(6)
}
}
)
-> base_type unsigned long byte_size(8) encoding(7)
Signed-off-by: Sami Tolvanen <samitolvanen@google.com>
Reviewed-by: Petr Pavlu <petr.pavlu@suse.com>
Signed-off-by: Masahiro Yamada <masahiroy@kernel.org>
This commit is contained in:
committed by
Masahiro Yamada
parent
06b8b036ab
commit
220a0857f3
@@ -212,6 +212,15 @@ DEFINE_PROCESS_UDATA_ATTRIBUTE(alignment)
|
||||
DEFINE_PROCESS_UDATA_ATTRIBUTE(byte_size)
|
||||
DEFINE_PROCESS_UDATA_ATTRIBUTE(encoding)
|
||||
|
||||
/* Match functions -- die_match_callback_t */
|
||||
#define DEFINE_MATCH(type) \
|
||||
static bool match_##type##_type(Dwarf_Die *die) \
|
||||
{ \
|
||||
return dwarf_tag(die) == DW_TAG_##type##_type; \
|
||||
}
|
||||
|
||||
DEFINE_MATCH(formal_parameter)
|
||||
|
||||
bool match_all(Dwarf_Die *die)
|
||||
{
|
||||
return true;
|
||||
@@ -224,19 +233,28 @@ int process_die_container(struct state *state, struct die *cache,
|
||||
Dwarf_Die current;
|
||||
int res;
|
||||
|
||||
/* Track the first item in lists. */
|
||||
if (state)
|
||||
state->first_list_item = true;
|
||||
|
||||
res = checkp(dwarf_child(die, ¤t));
|
||||
while (!res) {
|
||||
if (match(¤t)) {
|
||||
/* <0 = error, 0 = continue, >0 = stop */
|
||||
res = checkp(func(state, cache, ¤t));
|
||||
if (res)
|
||||
return res;
|
||||
goto out;
|
||||
}
|
||||
|
||||
res = checkp(dwarf_siblingof(¤t, ¤t));
|
||||
}
|
||||
|
||||
return 0;
|
||||
res = 0;
|
||||
out:
|
||||
if (state)
|
||||
state->first_list_item = false;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static int process_type(struct state *state, struct die *parent,
|
||||
@@ -256,6 +274,40 @@ static void process_type_attr(struct state *state, struct die *cache,
|
||||
process(cache, "base_type void");
|
||||
}
|
||||
|
||||
static void process_list_comma(struct state *state, struct die *cache)
|
||||
{
|
||||
if (state->first_list_item) {
|
||||
state->first_list_item = false;
|
||||
} else {
|
||||
process(cache, " ,");
|
||||
process_linebreak(cache, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Comma-separated with DW_AT_type */
|
||||
static void __process_list_type(struct state *state, struct die *cache,
|
||||
Dwarf_Die *die, const char *type)
|
||||
{
|
||||
const char *name = get_name_attr(die);
|
||||
|
||||
process_list_comma(state, cache);
|
||||
process(cache, type);
|
||||
process_type_attr(state, cache, die);
|
||||
if (name) {
|
||||
process(cache, " ");
|
||||
process(cache, name);
|
||||
}
|
||||
}
|
||||
|
||||
#define DEFINE_PROCESS_LIST_TYPE(type) \
|
||||
static void process_##type##_type(struct state *state, \
|
||||
struct die *cache, Dwarf_Die *die) \
|
||||
{ \
|
||||
__process_list_type(state, cache, die, #type " "); \
|
||||
}
|
||||
|
||||
DEFINE_PROCESS_LIST_TYPE(formal_parameter)
|
||||
|
||||
/* Container types with DW_AT_type */
|
||||
static void __process_type(struct state *state, struct die *cache,
|
||||
Dwarf_Die *die, const char *type)
|
||||
@@ -290,6 +342,29 @@ DEFINE_PROCESS_TYPE(shared)
|
||||
DEFINE_PROCESS_TYPE(volatile)
|
||||
DEFINE_PROCESS_TYPE(typedef)
|
||||
|
||||
static void __process_subroutine_type(struct state *state, struct die *cache,
|
||||
Dwarf_Die *die, const char *type)
|
||||
{
|
||||
process(cache, type);
|
||||
process(cache, " (");
|
||||
process_linebreak(cache, 1);
|
||||
/* Parameters */
|
||||
check(process_die_container(state, cache, die, process_type,
|
||||
match_formal_parameter_type));
|
||||
process_linebreak(cache, -1);
|
||||
process(cache, ")");
|
||||
process_linebreak(cache, 0);
|
||||
/* Return type */
|
||||
process(cache, "-> ");
|
||||
process_type_attr(state, cache, die);
|
||||
}
|
||||
|
||||
static void process_subroutine_type(struct state *state, struct die *cache,
|
||||
Dwarf_Die *die)
|
||||
{
|
||||
__process_subroutine_type(state, cache, die, "subroutine_type");
|
||||
}
|
||||
|
||||
static void process_base_type(struct state *state, struct die *cache,
|
||||
Dwarf_Die *die)
|
||||
{
|
||||
@@ -360,8 +435,11 @@ static int process_type(struct state *state, struct die *parent, Dwarf_Die *die)
|
||||
PROCESS_TYPE(rvalue_reference)
|
||||
PROCESS_TYPE(shared)
|
||||
PROCESS_TYPE(volatile)
|
||||
/* Subtypes */
|
||||
PROCESS_TYPE(formal_parameter)
|
||||
/* Other types */
|
||||
PROCESS_TYPE(base)
|
||||
PROCESS_TYPE(subroutine)
|
||||
PROCESS_TYPE(typedef)
|
||||
default:
|
||||
debug("unimplemented type: %x", tag);
|
||||
@@ -391,7 +469,7 @@ static void process_symbol(struct state *state, Dwarf_Die *die,
|
||||
static int __process_subprogram(struct state *state, struct die *cache,
|
||||
Dwarf_Die *die)
|
||||
{
|
||||
process(cache, "subprogram");
|
||||
__process_subroutine_type(state, cache, die, "subprogram");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -60,6 +60,7 @@ extern int dump_dies;
|
||||
#define checkp(expr) __check(expr, __res < 0)
|
||||
|
||||
/* Consistent aliases (DW_TAG_<type>_type) for DWARF tags */
|
||||
#define DW_TAG_formal_parameter_type DW_TAG_formal_parameter
|
||||
#define DW_TAG_typedef_type DW_TAG_typedef
|
||||
|
||||
/*
|
||||
@@ -154,6 +155,9 @@ void die_map_free(void);
|
||||
struct state {
|
||||
struct symbol *sym;
|
||||
Dwarf_Die die;
|
||||
|
||||
/* List expansion */
|
||||
bool first_list_item;
|
||||
};
|
||||
|
||||
typedef int (*die_callback_t)(struct state *state, struct die *cache,
|
||||
|
||||
Reference in New Issue
Block a user