@@ -130,6 +130,18 @@ void die_map_add_string(struct die *cd, const char *str)
df->type = FRAGMENT_STRING;
}
+void die_map_add_linebreak(struct die *cd, int linebreak)
+{
+ struct die_fragment *df;
+
+ if (!cd)
+ return;
+
+ df = append_item(cd);
+ df->data.linebreak = linebreak;
+ df->type = FRAGMENT_LINEBREAK;
+}
+
void die_map_add_die(struct die *cd, struct die *child)
{
struct die_fragment *df;
@@ -6,6 +6,17 @@
#include <stdarg.h>
#include "gendwarfksyms.h"
+static bool do_linebreak;
+static int indentation_level;
+
+/* Line breaks and indentation for pretty-printing */
+static void process_linebreak(struct die *cache, int n)
+{
+ indentation_level += n;
+ do_linebreak = true;
+ die_map_add_linebreak(cache, n);
+}
+
#define DEFINE_GET_ATTR(attr, type) \
static bool get_##attr##_attr(Dwarf_Die *die, unsigned int id, \
type *value) \
@@ -75,6 +86,12 @@ static void process(struct die *cache, const char *s)
{
s = s ?: "<null>";
+ if (dump_dies && do_linebreak) {
+ fputs("\n", stderr);
+ for (int i = 0; i < indentation_level; i++)
+ fputs(" ", stderr);
+ do_linebreak = false;
+ }
if (dump_dies)
fputs(s, stderr);
@@ -238,6 +255,40 @@ static void process_type_attr(struct state *state, struct die *cache,
process(cache, "base_type void");
}
+/* Container types with DW_AT_type */
+static void __process_type(struct state *state, struct die *cache,
+ Dwarf_Die *die, const char *type)
+{
+ process(cache, type);
+ process_fqn(cache, die);
+ process(cache, " {");
+ process_linebreak(cache, 1);
+ process_type_attr(state, cache, die);
+ process_linebreak(cache, -1);
+ process(cache, "}");
+ process_byte_size_attr(cache, die);
+ process_alignment_attr(cache, die);
+}
+
+#define DEFINE_PROCESS_TYPE(type) \
+ static void process_##type##_type(struct state *state, \
+ struct die *cache, Dwarf_Die *die) \
+ { \
+ __process_type(state, cache, die, #type "_type"); \
+ }
+
+DEFINE_PROCESS_TYPE(atomic)
+DEFINE_PROCESS_TYPE(const)
+DEFINE_PROCESS_TYPE(immutable)
+DEFINE_PROCESS_TYPE(packed)
+DEFINE_PROCESS_TYPE(pointer)
+DEFINE_PROCESS_TYPE(reference)
+DEFINE_PROCESS_TYPE(restrict)
+DEFINE_PROCESS_TYPE(rvalue_reference)
+DEFINE_PROCESS_TYPE(shared)
+DEFINE_PROCESS_TYPE(volatile)
+DEFINE_PROCESS_TYPE(typedef)
+
static void process_base_type(struct state *state, struct die *cache,
Dwarf_Die *die)
{
@@ -259,6 +310,9 @@ static void process_cached(struct state *state, struct die *cache,
case FRAGMENT_STRING:
process(NULL, df->data.str);
break;
+ case FRAGMENT_LINEBREAK:
+ process_linebreak(NULL, df->data.linebreak);
+ break;
case FRAGMENT_DIE:
if (!dwarf_die_addr_die(dwarf_cu_getdwarf(die->cu),
(void *)df->data.addr, &child))
@@ -294,7 +348,20 @@ static int process_type(struct state *state, struct die *parent, Dwarf_Die *die)
}
switch (tag) {
+ /* Type modifiers */
+ PROCESS_TYPE(atomic)
+ PROCESS_TYPE(const)
+ PROCESS_TYPE(immutable)
+ PROCESS_TYPE(packed)
+ PROCESS_TYPE(pointer)
+ PROCESS_TYPE(reference)
+ PROCESS_TYPE(restrict)
+ PROCESS_TYPE(rvalue_reference)
+ PROCESS_TYPE(shared)
+ PROCESS_TYPE(volatile)
+ /* Other types */
PROCESS_TYPE(base)
+ PROCESS_TYPE(typedef)
default:
debug("unimplemented type: %x", tag);
break;
@@ -64,6 +64,9 @@ extern int dump_dies;
/* Error == negative values */
#define checkp(expr) __check(expr, __res < 0)
+/* Consistent aliases (DW_TAG_<type>_type) for DWARF tags */
+#define DW_TAG_typedef_type DW_TAG_typedef
+
/*
* symbols.c
*/
@@ -105,6 +108,7 @@ enum die_state {
enum die_fragment_type {
FRAGMENT_EMPTY,
FRAGMENT_STRING,
+ FRAGMENT_LINEBREAK,
FRAGMENT_DIE
};
@@ -112,6 +116,7 @@ struct die_fragment {
enum die_fragment_type type;
union {
char *str;
+ int linebreak;
uintptr_t addr;
} data;
struct list_head list;