summaryrefslogtreecommitdiff
path: root/usr.bin/ctfconv
diff options
context:
space:
mode:
authorMartin Pieuchot <mpi@cvs.openbsd.org>2017-10-31 10:08:52 +0000
committerMartin Pieuchot <mpi@cvs.openbsd.org>2017-10-31 10:08:52 +0000
commit82d1938585b1156e1c6b6d7f7fc5733110b99ed6 (patch)
treebdc082d82bd1b075a71741ae9d89ab3af0c415ea /usr.bin/ctfconv
parent6c5e67580e475745e06b9219a0397210ebc416ea (diff)
Merge type forward declarations with real ones as soon as they are found.
Diffstat (limited to 'usr.bin/ctfconv')
-rw-r--r--usr.bin/ctfconv/itype.h4
-rw-r--r--usr.bin/ctfconv/parse.c55
2 files changed, 45 insertions, 14 deletions
diff --git a/usr.bin/ctfconv/itype.h b/usr.bin/ctfconv/itype.h
index 314c7fed08d..408a2140558 100644
--- a/usr.bin/ctfconv/itype.h
+++ b/usr.bin/ctfconv/itype.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: itype.h,v 1.3 2017/08/11 16:28:30 mpi Exp $ */
+/* $OpenBSD: itype.h,v 1.4 2017/10/31 10:08:51 mpi Exp $ */
/*
* Copyright (c) 2016-2017 Martin Pieuchot
@@ -58,7 +58,7 @@ struct itype {
#define ITF_UNRES_MEMB 0x02 /* members need to be resolved */
#define ITF_FUNC 0x04 /* is a function */
#define ITF_OBJ 0x08 /* is an object */
-#define ITF_VARARGS 0x10 /* takes varargs */
+#define ITF_FORWARD 0x10 /* is a forward declaration */
#define ITF_INSERTED 0x20 /* already found/inserted */
#define ITF_USED 0x40 /* referenced in the current CU */
#define ITF_ANON 0x80 /* type without name */
diff --git a/usr.bin/ctfconv/parse.c b/usr.bin/ctfconv/parse.c
index 6c8f9b259c6..0d25bb3890b 100644
--- a/usr.bin/ctfconv/parse.c
+++ b/usr.bin/ctfconv/parse.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: parse.c,v 1.9 2017/10/28 13:23:26 mpi Exp $ */
+/* $OpenBSD: parse.c,v 1.10 2017/10/31 10:08:51 mpi Exp $ */
/*
* Copyright (c) 2016-2017 Martin Pieuchot
@@ -105,6 +105,7 @@ const char *enc2name(unsigned short);
struct itype *it_new(uint64_t, size_t, const char *, uint32_t, uint16_t,
uint64_t, uint16_t, unsigned int);
+void it_merge(struct itype *, struct itype *);
void it_reference(struct itype *);
void it_free(struct itype *);
int it_cmp(struct itype *, struct itype *);
@@ -247,6 +248,30 @@ it_dup(struct itype *it)
return copit;
}
+/*
+ * Merge the content of ``it'', the full type declaration into the
+ * forwarding representation ``fwd''.
+ */
+void
+it_merge(struct itype *fwd, struct itype *it)
+{
+ assert(fwd->it_flags & ITF_FORWARD);
+ assert(fwd->it_type == it->it_type);
+ assert(TAILQ_EMPTY(&fwd->it_members));
+ assert(SIMPLEQ_EMPTY(&it->it_refs));
+
+ fwd->it_off = it->it_off;
+ fwd->it_ref = it->it_ref;
+ fwd->it_refp = it->it_refp;
+ fwd->it_size = it->it_size;
+ fwd->it_nelems = it->it_nelems;
+ fwd->it_enc = it->it_enc;
+ fwd->it_flags = it->it_flags;
+
+ TAILQ_CONCAT(&fwd->it_members, &it->it_members, im_next);
+ assert(TAILQ_EMPTY(&it->it_members));
+}
+
const char *
it_name(struct itype *it)
{
@@ -299,12 +324,6 @@ it_cmp(struct itype *a, struct itype *b)
if ((diff = (a->it_type - b->it_type)) != 0)
return diff;
- if ((diff = (a->it_size - b->it_size)) != 0)
- return diff;
-
- if ((diff = (a->it_nelems - b->it_nelems)) != 0)
- return diff;
-
/* Match by name */
if (!(a->it_flags & ITF_ANON) && !(b->it_flags & ITF_ANON))
return strcmp(it_name(a), it_name(b));
@@ -539,6 +558,11 @@ cu_merge(struct dwcu *dcu, struct itype_queue *cutq)
}
}
+ /* If we first got a forward reference, complete it. */
+ if ((prev->it_flags & ITF_FORWARD) &&
+ (old->it_flags & ITF_FORWARD) == 0)
+ it_merge(prev, old);
+
old->it_flags &= ~ITF_USED;
} else if (it->it_flags & ITF_USED) {
RB_INSERT(itype_tree, &itypet[it->it_type], it);
@@ -971,10 +995,15 @@ parse_struct(struct dwdie *die, size_t psz, int type, size_t off)
struct itype *it = NULL;
struct dwaval *dav;
const char *name = NULL;
+ unsigned int flags = 0;
size_t size = 0;
+ int forward = 0;
SIMPLEQ_FOREACH(dav, &die->die_avals, dav_next) {
switch (dav->dav_dat->dat_attr) {
+ case DW_AT_declaration:
+ forward = dav2val(dav, psz);
+ break;
case DW_AT_byte_size:
size = dav2val(dav, psz);
assert(size < UINT_MAX);
@@ -988,8 +1017,10 @@ parse_struct(struct dwdie *die, size_t psz, int type, size_t off)
}
}
- it = it_new(++tidx, die->die_offset, name, size, 0, 0, type, 0);
+ if (forward)
+ flags = ITF_FORWARD;
+ it = it_new(++tidx, die->die_offset, name, size, 0, 0, type, flags);
subparse_member(die, psz, it, off);
return it;
@@ -1094,7 +1125,7 @@ subparse_arguments(struct dwdie *die, size_t psz, struct itype *it)
uint64_t tag = die->die_dab->dab_tag;
if (tag == DW_TAG_unspecified_parameters) {
- it->it_flags |= ITF_VARARGS;
+ /* TODO */
continue;
}
@@ -1227,12 +1258,12 @@ parse_variable(struct dwdie *die, size_t psz)
struct dwaval *dav;
const char *name = NULL;
size_t ref = 0;
- int declaration = 0;
+ int forward = 0;
SIMPLEQ_FOREACH(dav, &die->die_avals, dav_next) {
switch (dav->dav_dat->dat_attr) {
case DW_AT_declaration:
- declaration = dav2val(dav, psz);
+ forward = dav2val(dav, psz);
break;
case DW_AT_name:
name = dav2str(dav);
@@ -1247,7 +1278,7 @@ parse_variable(struct dwdie *die, size_t psz)
}
- if (!declaration && name != NULL) {
+ if (!forward && name != NULL) {
it = it_new(++oidx, die->die_offset, name, 0, 0, ref, 0,
ITF_UNRES|ITF_OBJ);
}