diff options
-rw-r--r-- | include/ChangeLog | 5 | ||||
-rw-r--r-- | include/ctf-api.h | 5 | ||||
-rw-r--r-- | ld/ChangeLog | 8 | ||||
-rw-r--r-- | ld/testsuite/ld-ctf/conflicting-cycle-1.parent.d | 4 | ||||
-rw-r--r-- | ld/testsuite/ld-ctf/cross-tu-cyclic-conflicting.d | 4 | ||||
-rw-r--r-- | ld/testsuite/ld-ctf/forward.c | 2 | ||||
-rw-r--r-- | ld/testsuite/ld-ctf/forward.d | 23 | ||||
-rw-r--r-- | libctf/ChangeLog | 13 | ||||
-rw-r--r-- | libctf/ctf-create.c | 50 | ||||
-rw-r--r-- | libctf/ctf-dump.c | 17 | ||||
-rw-r--r-- | libctf/ctf-types.c | 28 |
11 files changed, 135 insertions, 24 deletions
diff --git a/include/ChangeLog b/include/ChangeLog index 048ba61..1b56987 100644 --- a/include/ChangeLog +++ b/include/ChangeLog @@ -1,3 +1,8 @@ +2021-01-05 Nick Alcock <nick.alcock@oracle.com> + + * ctf-api.h (ECTF_INCOMPLETE): New. + (ECTF_NERR): Adjust. + 2021-01-01 Nicolas Boulenguez <nicolas@debian.org> * coff/internal.h: Correct comment spelling. diff --git a/include/ctf-api.h b/include/ctf-api.h index f221d17..b3cfd39 100644 --- a/include/ctf-api.h +++ b/include/ctf-api.h @@ -230,7 +230,8 @@ typedef struct ctf_snapshot_id _CTF_ITEM (ECTF_NEXT_WRONGFUN, "Wrong iteration function called.") \ _CTF_ITEM (ECTF_NEXT_WRONGFP, "Iteration entity changed in mid-iterate.") \ _CTF_ITEM (ECTF_FLAGS, "CTF header contains flags unknown to libctf.") \ - _CTF_ITEM (ECTF_NEEDSBFD, "This feature needs a libctf with BFD support.") + _CTF_ITEM (ECTF_NEEDSBFD, "This feature needs a libctf with BFD support.") \ + _CTF_ITEM (ECTF_INCOMPLETE, "Type is not a complete type.") #define ECTF_BASE 1000 /* Base value for libctf errnos. */ @@ -243,7 +244,7 @@ _CTF_ERRORS #undef _CTF_FIRST }; -#define ECTF_NERR (ECTF_NEEDSBFD - ECTF_BASE + 1) /* Count of CTF errors. */ +#define ECTF_NERR (ECTF_INCOMPLETE - ECTF_BASE + 1) /* Count of CTF errors. */ /* The CTF data model is inferred to be the caller's data model or the data model of the given object, unless ctf_setmodel is explicitly called. */ diff --git a/ld/ChangeLog b/ld/ChangeLog index a130c6c..1497fc4 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,5 +1,13 @@ 2021-01-05 Nick Alcock <nick.alcock@oracle.com> + * testsuite/ld-ctf/conflicting-cycle-1.parent.d: Adjust for dumper + changes. + * testsuite/ld-ctf/cross-tu-cyclic-conflicting.d: Likewise. + * testsuite/ld-ctf/forward.c: New test... + * testsuite/ld-ctf/forward.d: ... and results. + +2021-01-05 Nick Alcock <nick.alcock@oracle.com> + * testsuite/ld-ctf/array.d: Adjust for dumper changes. * testsuite/ld-ctf/data-func-conflicted.d: Likewise. * testsuite/ld-ctf/diag-cttname-null.d: Likewise. diff --git a/ld/testsuite/ld-ctf/conflicting-cycle-1.parent.d b/ld/testsuite/ld-ctf/conflicting-cycle-1.parent.d index 4cbe9b6..5da66fda 100644 --- a/ld/testsuite/ld-ctf/conflicting-cycle-1.parent.d +++ b/ld/testsuite/ld-ctf/conflicting-cycle-1.parent.d @@ -29,8 +29,8 @@ Contents of CTF section .ctf: #... Types: #... - 0x[0-9a-f]*: struct B \(.* - *\[0x0\] \(ID 0x[0-9a-f]*\) \(kind 9\) struct B \(.* + 0x[0-9a-f]*: struct B + *\[0x0\] \(ID 0x[0-9a-f]*\) \(kind 9\) struct B #... CTF archive member: .*: #... diff --git a/ld/testsuite/ld-ctf/cross-tu-cyclic-conflicting.d b/ld/testsuite/ld-ctf/cross-tu-cyclic-conflicting.d index 3c975eb..eff295e 100644 --- a/ld/testsuite/ld-ctf/cross-tu-cyclic-conflicting.d +++ b/ld/testsuite/ld-ctf/cross-tu-cyclic-conflicting.d @@ -23,8 +23,8 @@ Contents of CTF section \.ctf: 0x[0-9a-f]*: int \[0x0:0x[0-9a-f]*\] \(size 0x[0-9a-f]*\) *\[0x0\] \(ID 0x[0-9a-f]*\) \(kind 1\) int:[0-9]* \(aligned at 0x[0-9a-f]*, format 0x1, offset:bits 0x0:0x[0-9a-f]*\) #... - 0x[0-9a-f]*: struct A .* - *\[0x0\] \(ID 0x[0-9a-f]*\) \(kind 9\) struct A .* + 0x[0-9a-f]*: struct A + *\[0x0\] \(ID 0x[0-9a-f]*\) \(kind 9\) struct A #... 0x[0-9a-f]*: struct C .* *\[0x0\] \(ID 0x[0-9a-f]*\) \(kind 6\) struct C .* diff --git a/ld/testsuite/ld-ctf/forward.c b/ld/testsuite/ld-ctf/forward.c new file mode 100644 index 0000000..e41a7ae --- /dev/null +++ b/ld/testsuite/ld-ctf/forward.c @@ -0,0 +1,2 @@ +struct foo; +struct foo *bar __attribute__((used)); diff --git a/ld/testsuite/ld-ctf/forward.d b/ld/testsuite/ld-ctf/forward.d new file mode 100644 index 0000000..9ff0dd2 --- /dev/null +++ b/ld/testsuite/ld-ctf/forward.d @@ -0,0 +1,23 @@ +#as: +#source: forward.c +#objdump: --ctf=.ctf +#ld: -shared +#name: Forwards + +.*: +file format .* + +Contents of CTF section .ctf: + + Header: + Magic number: 0xdff2 + Version: 4 \(CTF_VERSION_3\) +#... + Type section: .* \(0x18 bytes\) +#... + Types: + + 0x[0-9a-f]: struct foo + *\[0x0\] \(ID 0x[0-9a-f]*\) \(kind 9\) struct foo + 0x[0-9a-f]: struct foo \* \(size 0x[0-9a-f]*\) -> 0x[0-9a-f]: struct foo + *\[0x0\] \(ID 0x[0-9a-f]\) \(kind 3\) struct foo \* \(aligned at 0x[0-9a-f]*\) +#... diff --git a/libctf/ChangeLog b/libctf/ChangeLog index 80f05e9..b914254 100644 --- a/libctf/ChangeLog +++ b/libctf/ChangeLog @@ -1,5 +1,18 @@ 2021-01-05 Nick Alcock <nick.alcock@oracle.com> + * ctf-types.c (ctf_type_resolve): Improve comment. + (ctf_type_size): Yield ECTF_INCOMPLETE when applied to forwards. + Emit errors into the right dict. + (ctf_type_align): Likewise. + * ctf-create.c (ctf_add_member_offset): Yield ECTF_INCOMPLETE + when adding a member without explicit offset when this member, or + the previous member, is incomplete. + * ctf-dump.c (ctf_dump_format_type): Do not try to print the size of + forwards. + (ctf_dump_member): Do not try to print their alignment. + +2021-01-05 Nick Alcock <nick.alcock@oracle.com> + * ctf-dump.c (ctf_dump_objts): Dump by calling ctf_dump_format_type. (ctf_dump_format_type): Don't emit the size for function objects. Dump the element type of arrays like we dump the pointed-to type of diff --git a/libctf/ctf-create.c b/libctf/ctf-create.c index 0af46d3..6fe7461 100644 --- a/libctf/ctf-create.c +++ b/libctf/ctf-create.c @@ -1690,6 +1690,14 @@ ctf_add_array (ctf_dict_t *fp, uint32_t flag, const ctf_arinfo_t *arp) if (ctf_lookup_by_id (&tmp, arp->ctr_index) == NULL) return CTF_ERR; /* errno is set for us. */ + if (ctf_type_kind (fp, arp->ctr_index) == CTF_K_FORWARD) + { + ctf_err_warn (fp, 1, ECTF_INCOMPLETE, + _("ctf_add_array: index type %lx is incomplete"), + arp->ctr_contents); + return (ctf_set_errno (fp, ECTF_INCOMPLETE)); + } + if ((type = ctf_add_generic (fp, flag, NULL, CTF_K_ARRAY, &dtd)) == CTF_ERR) return CTF_ERR; /* errno is set for us. */ @@ -2040,6 +2048,7 @@ ctf_add_member_offset (ctf_dict_t *fp, ctf_id_t souid, const char *name, ssize_t msize, malign, ssize; uint32_t kind, vlen, root; char *s = NULL; + int is_incomplete = 0; if (!(fp->ctf_flags & LCTF_RDWR)) return (ctf_set_errno (fp, ECTF_RDONLY)); @@ -2075,14 +2084,19 @@ ctf_add_member_offset (ctf_dict_t *fp, ctf_id_t souid, const char *name, { /* The unimplemented type, and any type that resolves to it, has no size and no alignment: it can correspond to any number of compiler-inserted - types. */ - + types. We allow incomplete types through since they are routinely + added to the ends of structures, and can even be added elsewhere in + structures by the deduplicator. They are assumed to be zero-size with + no alignment: this is often wrong, but problems can be avoided in this + case by explicitly specifying the size of the structure via the _sized + functions. The deduplicator always does this. */ + + msize = 0; + malign = 0; if (ctf_errno (fp) == ECTF_NONREPRESENTABLE) - { - msize = 0; - malign = 0; - ctf_set_errno (fp, 0); - } + ctf_set_errno (fp, 0); + else if (ctf_errno (fp) == ECTF_INCOMPLETE) + is_incomplete = 1; else return -1; /* errno is set for us. */ } @@ -2123,10 +2137,32 @@ ctf_add_member_offset (ctf_dict_t *fp, ctf_id_t souid, const char *name, return -1; /* errno is set for us. */ } + if (is_incomplete) + { + ctf_err_warn (fp, 1, ECTF_INCOMPLETE, + _("ctf_add_member_offset: cannot add member %s of " + "incomplete type %lx to struct %lx without " + "specifying explicit offset\n"), + name ? name : _("(unnamed member)"), type, souid); + return (ctf_set_errno (fp, ECTF_INCOMPLETE)); + } + if (ctf_type_encoding (fp, ltype, &linfo) == 0) off += linfo.cte_bits; else if ((lsize = ctf_type_size (fp, ltype)) > 0) off += lsize * CHAR_BIT; + else if (lsize == -1 && ctf_errno (fp) == ECTF_INCOMPLETE) + { + ctf_err_warn (fp, 1, ECTF_INCOMPLETE, + _("ctf_add_member_offset: cannot add member %s of " + "type %lx to struct %lx without specifying " + "explicit offset after member %s of type %lx, " + "which is an incomplete type\n"), + name ? name : _("(unnamed member)"), type, souid, + lmd->dmd_name ? lmd->dmd_name + : _("(unnamed member)"), ltype); + return -1; /* errno is set for us. */ + } /* Round up the offset of the end of the last member to the next byte boundary, convert 'off' to bytes, and diff --git a/libctf/ctf-dump.c b/libctf/ctf-dump.c index f01f225..abed483 100644 --- a/libctf/ctf-dump.c +++ b/libctf/ctf-dump.c @@ -151,7 +151,7 @@ ctf_dump_format_type (ctf_dict_t *fp, ctf_id_t id, int flag) free (bit); bit = NULL; - if (kind != CTF_K_FUNCTION) + if (kind != CTF_K_FUNCTION && kind != CTF_K_FORWARD) if (asprintf (&bit, " (size 0x%lx)%s", (unsigned long) ctf_type_size (fp, id), nonroot_trailer) < 0) @@ -476,6 +476,7 @@ ctf_dump_member (const char *name, ctf_id_t id, unsigned long offset, char *bit = NULL; ctf_encoding_t ep; int has_encoding = 0; + int opened_paren = 0; /* Align neatly. */ @@ -520,8 +521,9 @@ ctf_dump_member (const char *name, ctf_id_t id, unsigned long offset, ep.cte_bits, (unsigned long) ctf_type_align (state->cdm_fp, id)) < 0) goto oom; + opened_paren = 1; } - else + else if (ctf_type_kind (state->cdm_fp, id) != CTF_K_FORWARD) { if (asprintf (&bit, "[0x%lx] (ID 0x%lx) (kind %i) %s%s%s " "(aligned at 0x%lx", offset, id, @@ -529,6 +531,14 @@ ctf_dump_member (const char *name, ctf_id_t id, unsigned long offset, (name[0] != 0 && typestr[0] != 0) ? " " : "", name, (unsigned long) ctf_type_align (state->cdm_fp, id)) < 0) goto oom; + opened_paren = 1; + } + else /* Forwards have no alignment. */ + { + if (asprintf (&bit, "[0x%lx] (ID 0x%lx) (kind %i) %s%s%s\n", offset, id, + ctf_type_kind (state->cdm_fp, id), typestr, + (name[0] != 0 && typestr[0] != 0) ? " " : "", name) < 0) + goto oom; } *state->cdm_str = str_append (*state->cdm_str, bit); @@ -547,7 +557,8 @@ ctf_dump_member (const char *name, ctf_id_t id, unsigned long offset, bit = NULL; } - *state->cdm_str = str_append (*state->cdm_str, ")\n"); + if (opened_paren) + *state->cdm_str = str_append (*state->cdm_str, ")\n"); return 0; oom: diff --git a/libctf/ctf-types.c b/libctf/ctf-types.c index 61891d6..3ba635f 100644 --- a/libctf/ctf-types.c +++ b/libctf/ctf-types.c @@ -583,7 +583,10 @@ ctf_variable_next (ctf_dict_t *fp, ctf_next_t **it, const char **name) against infinite loops, we implement simplified cycle detection and check each link against itself, the previous node, and the topmost node. - Does not drill down through slices to their contained type. */ + Does not drill down through slices to their contained type. + + Callers of this function must not presume that a type it returns must have a + valid ctt_size: forwards do not, and must be separately handled. */ ctf_id_t ctf_type_resolve (ctf_dict_t *fp, ctf_id_t type) @@ -911,6 +914,7 @@ ctf_type_aname_raw (ctf_dict_t *fp, ctf_id_t type) ssize_t ctf_type_size (ctf_dict_t *fp, ctf_id_t type) { + ctf_dict_t *ofp = fp; const ctf_type_t *tp; ssize_t size; ctf_arinfo_t ar; @@ -942,12 +946,16 @@ ctf_type_size (ctf_dict_t *fp, ctf_id_t type) if ((size = ctf_get_ctt_size (fp, tp, NULL, NULL)) > 0) return size; - if (ctf_array_info (fp, type, &ar) < 0 - || (size = ctf_type_size (fp, ar.ctr_contents)) < 0) + if (ctf_array_info (ofp, type, &ar) < 0 + || (size = ctf_type_size (ofp, ar.ctr_contents)) < 0) return -1; /* errno is set for us. */ return size * ar.ctr_nelems; + case CTF_K_FORWARD: + /* Forwards do not have a meaningful size. */ + return (ctf_set_errno (ofp, ECTF_INCOMPLETE)); + default: /* including slices of enums, etc */ return (ctf_get_ctt_size (fp, tp, NULL, NULL)); } @@ -981,9 +989,9 @@ ctf_type_align (ctf_dict_t *fp, ctf_id_t type) case CTF_K_ARRAY: { ctf_arinfo_t r; - if (ctf_array_info (fp, type, &r) < 0) + if (ctf_array_info (ofp, type, &r) < 0) return -1; /* errno is set for us. */ - return (ctf_type_align (fp, r.ctr_contents)); + return (ctf_type_align (ofp, r.ctr_contents)); } case CTF_K_STRUCT: @@ -1009,7 +1017,7 @@ ctf_type_align (ctf_dict_t *fp, ctf_id_t type) const ctf_member_t *mp = vmp; for (; n != 0; n--, mp++) { - ssize_t am = ctf_type_align (fp, mp->ctm_type); + ssize_t am = ctf_type_align (ofp, mp->ctm_type); align = MAX (align, (size_t) am); } } @@ -1018,7 +1026,7 @@ ctf_type_align (ctf_dict_t *fp, ctf_id_t type) const ctf_lmember_t *lmp = vmp; for (; n != 0; n--, lmp++) { - ssize_t am = ctf_type_align (fp, lmp->ctlm_type); + ssize_t am = ctf_type_align (ofp, lmp->ctlm_type); align = MAX (align, (size_t) am); } } @@ -1030,7 +1038,7 @@ ctf_type_align (ctf_dict_t *fp, ctf_id_t type) for (dmd = ctf_list_next (&dtd->dtd_u.dtu_members); dmd != NULL; dmd = ctf_list_next (dmd)) { - ssize_t am = ctf_type_align (fp, dmd->dmd_type); + ssize_t am = ctf_type_align (ofp, dmd->dmd_type); align = MAX (align, (size_t) am); if (kind == CTF_K_STRUCT) break; @@ -1043,6 +1051,10 @@ ctf_type_align (ctf_dict_t *fp, ctf_id_t type) case CTF_K_ENUM: return fp->ctf_dmodel->ctd_int; + case CTF_K_FORWARD: + /* Forwards do not have a meaningful alignment. */ + return (ctf_set_errno (ofp, ECTF_INCOMPLETE)); + default: /* including slices of enums, etc */ return (ctf_get_ctt_size (fp, tp, NULL, NULL)); } |