Commit 220a0857 authored by Sami Tolvanen's avatar Sami Tolvanen Committed by Masahiro Yamada
Browse files

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: default avatarSami Tolvanen <samitolvanen@google.com>
Reviewed-by: default avatarPetr Pavlu <petr.pavlu@suse.com>
Signed-off-by: default avatarMasahiro Yamada <masahiroy@kernel.org>
parent 06b8b036
Loading
Loading
Loading
Loading
+81 −3
Original line number Diff line number Diff line
@@ -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, &current));
	while (!res) {
		if (match(&current)) {
			/* <0 = error, 0 = continue, >0 = stop */
			res = checkp(func(state, cache, &current));
			if (res)
				return res;
				goto out;
		}

		res = checkp(dwarf_siblingof(&current, &current));
	}

	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;
}

+4 −0
Original line number Diff line number Diff line
@@ -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,