diff options
-rw-r--r-- | include/ChangeLog | 4 | ||||
-rw-r--r-- | include/ctf-api.h | 3 | ||||
-rw-r--r-- | libctf/ChangeLog | 22 | ||||
-rw-r--r-- | libctf/ctf-create.c | 19 | ||||
-rw-r--r-- | libctf/ctf-dump.c | 90 | ||||
-rw-r--r-- | libctf/ctf-error.c | 3 | ||||
-rw-r--r-- | libctf/ctf-link.c | 18 | ||||
-rw-r--r-- | libctf/ctf-types.c | 5 |
8 files changed, 136 insertions, 28 deletions
diff --git a/include/ChangeLog b/include/ChangeLog index a0d3c10d9cd..1f9534269e6 100644 --- a/include/ChangeLog +++ b/include/ChangeLog @@ -1,3 +1,7 @@ +2019-08-05 Nick Alcock <nick.alcock@oracle.com> + + * ctf-api.h (ECTF_NONREPRESENTABLE): New. + 2019-09-23 Nick Alcock <nick.alcock@oracle.com> * ctf-api.h: Note the instability of the ctf_link interfaces. diff --git a/include/ctf-api.h b/include/ctf-api.h index 674860d52f3..b83ddc7a3be 100644 --- a/include/ctf-api.h +++ b/include/ctf-api.h @@ -203,7 +203,8 @@ enum ECTF_DUMPSECTUNKNOWN, /* Unknown section number in dump. */ ECTF_DUMPSECTCHANGED, /* Section changed in middle of dump. */ ECTF_NOTYET, /* Feature not yet implemented. */ - ECTF_INTERNAL /* Internal error in link. */ + ECTF_INTERNAL, /* Internal error in link. */ + ECTF_NONREPRESENTABLE /* Type not representable in CTF. */ }; /* The CTF data model is inferred to be the caller's data model or the data diff --git a/libctf/ChangeLog b/libctf/ChangeLog index b84f6a61e8d..f3e136f21ea 100644 --- a/libctf/ChangeLog +++ b/libctf/ChangeLog @@ -1,3 +1,25 @@ +2019-08-05 Nick Alcock <nick.alcock@oracle.com> + + * ctf-types.c (ctf_type_resolve): Return ECTF_NONREPRESENTABLE on + type zero. + * ctf-create.c (ctf_add_type): Detect and skip nonrepresentable + members and types. + (ctf_add_variable): Likewise for variables pointing to them. + * ctf-link.c (ctf_link_one_type): Do not warn for nonrepresentable + type link failure, but do warn for others. + * ctf-dump.c (ctf_dump_format_type): Likewise. Do not assume all + errors to be ENOMEM. + (ctf_dump_member): Likewise. + (ctf_dump_type): Likewise. + (ctf_dump_header_strfield): Do not assume all errors to be ENOMEM. + (ctf_dump_header_sectfield): Do not assume all errors to be ENOMEM. + (ctf_dump_header): Likewise. + (ctf_dump_label): likewise. + (ctf_dump_objts): likewise. + (ctf_dump_funcs): likewise. + (ctf_dump_var): likewise. + (ctf_dump_str): Likewise. + 2019-09-30 Nick Alcock <nick.alcock@oracle.com> * configure.ac (AC_DISABLE_SHARED): New, like opcodes/. diff --git a/libctf/ctf-create.c b/libctf/ctf-create.c index 8eb16738a11..466777acffb 100644 --- a/libctf/ctf-create.c +++ b/libctf/ctf-create.c @@ -1439,6 +1439,11 @@ ctf_add_variable (ctf_file_t *fp, const char *name, ctf_id_t ref) if (ctf_lookup_by_id (&tmp, ref) == NULL) return -1; /* errno is set for us. */ + /* Make sure this type is representable. */ + if ((ctf_type_resolve (fp, ref) == CTF_ERR) + && (ctf_errno (fp) == ECTF_NONREPRESENTABLE)) + return -1; + if ((dvd = ctf_alloc (sizeof (ctf_dvdef_t))) == NULL) return (ctf_set_errno (fp, EAGAIN)); @@ -1571,6 +1576,10 @@ ctf_add_type (ctf_file_t *dst_fp, ctf_file_t *src_fp, ctf_id_t src_type) if ((src_tp = ctf_lookup_by_id (&src_fp, src_type)) == NULL) return (ctf_set_errno (dst_fp, ctf_errno (src_fp))); + if ((ctf_type_resolve (src_fp, src_type) == CTF_ERR) + && (ctf_errno (src_fp) == ECTF_NONREPRESENTABLE)) + return (ctf_set_errno (dst_fp, ECTF_NONREPRESENTABLE)); + name = ctf_strptr (src_fp, src_tp->ctt_name); kind = LCTF_INFO_KIND (src_fp, src_tp->ctt_info); flag = LCTF_INFO_ISROOT (src_fp, src_tp->ctt_info); @@ -1906,13 +1915,19 @@ ctf_add_type (ctf_file_t *dst_fp, ctf_file_t *src_fp, ctf_id_t src_type) /* Make a final pass through the members changing each dmd_type (a src_fp type) to an equivalent type in dst_fp. We pass through all - members, leaving any that fail set to CTF_ERR. */ + members, leaving any that fail set to CTF_ERR, unless they fail + because they are marking a member of type not representable in this + version of CTF, in which case we just want to silently omit them: + no consumer can do anything with them anyway. */ for (dmd = ctf_list_next (&dtd->dtd_u.dtu_members); dmd != NULL; dmd = ctf_list_next (dmd)) { if ((dmd->dmd_type = ctf_add_type (dst_fp, src_fp, dmd->dmd_type)) == CTF_ERR) - errs++; + { + if (ctf_errno (dst_fp) != ECTF_NONREPRESENTABLE) + errs++; + } } if (errs) diff --git a/libctf/ctf-dump.c b/libctf/ctf-dump.c index 2a888e13639..df08f0b2a7a 100644 --- a/libctf/ctf-dump.c +++ b/libctf/ctf-dump.c @@ -116,7 +116,16 @@ ctf_dump_format_type (ctf_file_t *fp, ctf_id_t id, int flag) buf = ctf_type_aname (fp, id); if (!buf) - goto oom; + { + if (id == 0 || ctf_errno (fp) == ECTF_NONREPRESENTABLE) + { + str = ctf_str_append (str, " (type not represented in CTF)"); + ctf_set_errno (fp, ECTF_NOTREF); + break; + } + + goto err; + } /* Slices get a different print representation. */ @@ -156,10 +165,11 @@ ctf_dump_format_type (ctf_file_t *fp, ctf_id_t id, int flag) return str; oom: + ctf_set_errno (fp, errno); + err: free (buf); free (str); free (bit); - ctf_set_errno (fp, ENOMEM); return NULL; } @@ -178,7 +188,7 @@ ctf_dump_header_strfield (ctf_file_t *fp, ctf_dump_state_t *state, return 0; err: - return (ctf_set_errno (fp, -ENOMEM)); + return (ctf_set_errno (fp, errno)); } /* Dump one section-offset field from the file header into the cds_items. */ @@ -198,7 +208,7 @@ ctf_dump_header_sectfield (ctf_file_t *fp, ctf_dump_state_t *state, return 0; err: - return (ctf_set_errno (fp, -ENOMEM)); + return (ctf_set_errno (fp, errno)); } /* Dump the file header into the cds_items. */ @@ -286,7 +296,7 @@ ctf_dump_header (ctf_file_t *fp, ctf_dump_state_t *state) return 0; err: - return (ctf_set_errno (fp, -ENOMEM)); + return (ctf_set_errno (fp, errno)); } /* Dump a single label into the cds_items. */ @@ -300,7 +310,7 @@ ctf_dump_label (const char *name, const ctf_lblinfo_t *info, ctf_dump_state_t *state = arg; if (asprintf (&str, "%s -> ", name) < 0) - return (ctf_set_errno (state->cds_fp, ENOMEM)); + return (ctf_set_errno (state->cds_fp, errno)); if ((typestr = ctf_dump_format_type (state->cds_fp, info->ctb_type, CTF_ADD_ROOT)) == NULL) @@ -350,12 +360,12 @@ ctf_dump_objts (ctf_file_t *fp, ctf_dump_state_t *state) if (sym_name[0] == '\0') { if (asprintf (&str, "%lx -> ", (unsigned long) i) < 0) - return (ctf_set_errno (fp, ENOMEM)); + return (ctf_set_errno (fp, errno)); } else { if (asprintf (&str, "%s (%lx) -> ", sym_name, (unsigned long) i) < 0) - return (ctf_set_errno (fp, ENOMEM)); + return (ctf_set_errno (fp, errno)); } /* Variable type. */ @@ -384,8 +394,9 @@ ctf_dump_funcs (ctf_file_t *fp, ctf_dump_state_t *state) for (i = 0; i < fp->ctf_nsyms; i++) { - char *str ; + char *str; char *bit; + const char *err; const char *sym_name; ctf_funcinfo_t fi; ctf_id_t type; @@ -410,7 +421,10 @@ ctf_dump_funcs (ctf_file_t *fp, ctf_dump_state_t *state) /* Return type. */ if ((str = ctf_type_aname (state->cds_fp, type)) == NULL) - goto err; + { + err = "look up return type"; + goto err; + } str = ctf_str_append (str, " "); @@ -434,12 +448,18 @@ ctf_dump_funcs (ctf_file_t *fp, ctf_dump_state_t *state) /* Function arguments. */ if (ctf_func_args (state->cds_fp, i, fi.ctc_argc, args) < 0) - goto err; + { + err = "look up argument type"; + goto err; + } for (j = 0; j < fi.ctc_argc; j++) { if ((bit = ctf_type_aname (state->cds_fp, args[j])) == NULL) - goto err; + { + err = "look up argument type name"; + goto err; + } str = ctf_str_append (str, bit); if ((j < fi.ctc_argc - 1) || (fi.ctc_flags & CTF_FUNC_VARARG)) str = ctf_str_append (str, ", "); @@ -457,8 +477,11 @@ ctf_dump_funcs (ctf_file_t *fp, ctf_dump_state_t *state) oom: free (args); free (str); - return (ctf_set_errno (fp, ENOMEM)); + return (ctf_set_errno (fp, errno)); err: + ctf_dprintf ("Cannot %s dumping function type for symbol 0x%li: %s\n", + err, (unsigned long) i, + ctf_errmsg (ctf_errno (state->cds_fp))); free (args); free (str); return -1; /* errno is set for us. */ @@ -475,7 +498,7 @@ ctf_dump_var (const char *name, ctf_id_t type, void *arg) ctf_dump_state_t *state = arg; if (asprintf (&str, "%s -> ", name) < 0) - return (ctf_set_errno (state->cds_fp, ENOMEM)); + return (ctf_set_errno (state->cds_fp, errno)); if ((typestr = ctf_dump_format_type (state->cds_fp, type, CTF_ADD_ROOT)) == NULL) @@ -506,7 +529,21 @@ ctf_dump_member (const char *name, ctf_id_t id, unsigned long offset, *state->cdm_str = ctf_str_append (*state->cdm_str, " "); if ((typestr = ctf_type_aname (state->cdm_fp, id)) == NULL) - goto oom; + { + if (id == 0 || ctf_errno (state->cdm_fp) == ECTF_NONREPRESENTABLE) + { + if (asprintf (&bit, " [0x%lx] (type not represented in CTF)", + offset) < 0) + goto oom; + + *state->cdm_str = ctf_str_append (*state->cdm_str, bit); + free (typestr); + free (bit); + return 0; + } + + goto oom; + } if (asprintf (&bit, " [0x%lx] (ID 0x%lx) (kind %i) %s %s (aligned at 0x%lx", offset, id, ctf_type_kind (state->cdm_fp, id), typestr, name, @@ -537,25 +574,36 @@ ctf_dump_member (const char *name, ctf_id_t id, unsigned long offset, oom: free (typestr); free (bit); - return (ctf_set_errno (state->cdm_fp, ENOMEM)); + return (ctf_set_errno (state->cdm_fp, errno)); } /* Dump a single type into the cds_items. */ - static int ctf_dump_type (ctf_id_t id, int flag, void *arg) { char *str; + const char *err; ctf_dump_state_t *state = arg; ctf_dump_membstate_t membstate = { &str, state->cds_fp }; size_t len; if ((str = ctf_dump_format_type (state->cds_fp, id, flag)) == NULL) - goto err; + { + err = "format type"; + goto err; + } str = ctf_str_append (str, "\n"); if ((ctf_type_visit (state->cds_fp, id, ctf_dump_member, &membstate)) < 0) - goto err; + { + if (id == 0 || ctf_errno (state->cds_fp) == ECTF_NONREPRESENTABLE) + { + ctf_dump_append (state, str); + return 0; + } + err = "visit members"; + goto err; + } /* Trim off the last linefeed added by ctf_dump_member(). */ len = strlen (str); @@ -566,6 +614,8 @@ ctf_dump_type (ctf_id_t id, int flag, void *arg) return 0; err: + ctf_dprintf ("Cannot %s dumping type 0x%lx: %s\n", err, id, + ctf_errmsg (ctf_errno (state->cds_fp))); free (str); return -1; /* errno is set for us. */ } @@ -584,7 +634,7 @@ ctf_dump_str (ctf_file_t *fp, ctf_dump_state_t *state) if (asprintf (&str, "%lx: %s", (unsigned long) (s - fp->ctf_str[CTF_STRTAB_0].cts_strs), s) < 0) - return (ctf_set_errno (fp, ENOMEM)); + return (ctf_set_errno (fp, errno)); ctf_dump_append (state, str); s += strlen (s) + 1; } diff --git a/libctf/ctf-error.c b/libctf/ctf-error.c index 93ffc6acc09..c0adb4bb519 100644 --- a/libctf/ctf-error.c +++ b/libctf/ctf-error.c @@ -70,7 +70,8 @@ static const char *const _ctf_errlist[] = { "Unknown section number in dump", /* ECTF_DUMPSECTUNKNOWN */ "Section changed in middle of dump", /* ECTF_DUMPSECTCHANGED */ "Feature not yet implemented", /* ECTF_NOTYET */ - "Internal error in link" /* ECTF_INTERNAL */ + "Internal error in link", /* ECTF_INTERNAL */ + "Type not representable in CTF" /* ECTF_NONREPRESENTABLE */ }; static const int _ctf_nerr = sizeof (_ctf_errlist) / sizeof (_ctf_errlist[0]); diff --git a/libctf/ctf-link.c b/libctf/ctf-link.c index 28c21132607..e2a03484115 100644 --- a/libctf/ctf-link.c +++ b/libctf/ctf-link.c @@ -348,10 +348,15 @@ ctf_link_one_type (ctf_id_t type, int isroot _libctf_unused_, void *arg_) err = ctf_errno (arg->out_fp); if (err != ECTF_CONFLICT) { - ctf_dprintf ("Cannot link type %lx from archive member %s, input file %s " - "into output link: %s\n", type, arg->arcname, arg->file_name, - ctf_errmsg (err)); - return -1; + if (err != ECTF_NONREPRESENTABLE) + ctf_dprintf ("Cannot link type %lx from archive member %s, input file %s " + "into output link: %s\n", type, arg->arcname, arg->file_name, + ctf_errmsg (err)); + /* We must ignore this problem or we end up losing future types, then + trying to link the variables in, then exploding. Better to link as + much as possible. XXX when we add a proper link warning + infrastructure, we should report the error here! */ + return 0; } ctf_set_errno (arg->out_fp, 0); } @@ -364,6 +369,11 @@ ctf_link_one_type (ctf_id_t type, int isroot _libctf_unused_, void *arg_) return 0; err = ctf_errno (per_cu_out_fp); + if (err != ECTF_NONREPRESENTABLE) + ctf_dprintf ("Cannot link type %lx from CTF archive member %s, input file %s " + "into output per-CU CTF archive member %s: %s: skipped\n", type, + arg->arcname, arg->file_name, arg->arcname, + ctf_errmsg (err)); if (err == ECTF_CONFLICT) /* Conflicts are possible at this stage only if a non-ld user has combined multiple TUs into a single output dictionary. Even in this case we do not diff --git a/libctf/ctf-types.c b/libctf/ctf-types.c index 95c9c9aca18..9fe4d5a6d73 100644 --- a/libctf/ctf-types.c +++ b/libctf/ctf-types.c @@ -200,6 +200,9 @@ ctf_type_resolve (ctf_file_t *fp, ctf_id_t type) ctf_file_t *ofp = fp; const ctf_type_t *tp; + if (type == 0) + return (ctf_set_errno (ofp, ECTF_NONREPRESENTABLE)); + while ((tp = ctf_lookup_by_id (&fp, type)) != NULL) { switch (LCTF_INFO_KIND (fp, tp->ctt_info)) @@ -220,6 +223,8 @@ ctf_type_resolve (ctf_file_t *fp, ctf_id_t type) default: return type; } + if (type == 0) + return (ctf_set_errno (ofp, ECTF_NONREPRESENTABLE)); } return CTF_ERR; /* errno is set for us. */ |