aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/ChangeLog4
-rw-r--r--include/ctf-api.h3
-rw-r--r--libctf/ChangeLog22
-rw-r--r--libctf/ctf-create.c19
-rw-r--r--libctf/ctf-dump.c90
-rw-r--r--libctf/ctf-error.c3
-rw-r--r--libctf/ctf-link.c18
-rw-r--r--libctf/ctf-types.c5
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. */