#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)                     \
 {
        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);
 
        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)
 {
                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))
        }
 
        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;