uint32_t cth_parlabel; /* Ref to name of parent lbl uniq'd against. */
uint32_t cth_parname; /* Ref to basename of parent. */
uint32_t cth_cuname; /* Ref to CU name (may be 0). */
+ uint32_t cth_parent_strlen; /* cth_strlen of parent (may be 0). */
uint32_t cth_lbloff; /* Offset of label section. */
uint32_t cth_objtoff; /* Offset of object section. */
uint32_t cth_funcoff; /* Offset of function section. */
#...
Parent name: \.ctf
Compilation unit name: .*/data-func-1\.c
+#...
Data object section: .* \(0x[1-9a-f][0-9a-f]* bytes\)
Type section: .* \(0xc bytes\)
String section: .*
#...
Parent name: \.ctf
Compilation unit name: .*/data-func-1\.c
+#...
Data object section: .* \(0x[1-9a-f][0-9a-f]* bytes\)
Type section: .* \(0xc bytes\)
String section: .*
return (ctf_set_errno (fp, errno));
}
+/* Dump one size field from the file header into the cds_items. */
+static int
+ctf_dump_header_sizefield (ctf_dict_t *fp, ctf_dump_state_t *state,
+ const char *name, uint32_t value)
+{
+ char *str;
+ if (value)
+ {
+ if (asprintf (&str, "%s: %x\n", name, value) < 0)
+ goto err;
+ ctf_dump_append (state, str);
+ }
+ return 0;
+
+ err:
+ return (ctf_set_errno (fp, errno));
+}
+
/* Dump one section-offset field from the file header into the cds_items. */
static int
ctf_dump_header_sectfield (ctf_dict_t *fp, ctf_dump_state_t *state,
hp->cth_cuname) < 0)
goto err;
+ if (ctf_dump_header_sizefield (fp, state, "Parent strlen", hp->cth_parent_strlen) < 0)
+ goto err;
+
if (ctf_dump_header_sectfield (fp, state, "Label section", hp->cth_lbloff,
hp->cth_objtoff) < 0)
goto err;
hp->cth_funcoff = oldhp->cth_funcoff;
hp->cth_objtoff = oldhp->cth_objtoff;
hp->cth_lbloff = oldhp->cth_lbloff;
+ hp->cth_parent_strlen = 0; /* Strings start at offset 0. */
hp->cth_cuname = 0; /* No CU name. */
}
hp->cth_funcoff = oldhp->cth_funcoff;
hp->cth_objtoff = oldhp->cth_objtoff;
hp->cth_lbloff = oldhp->cth_lbloff;
+ hp->cth_parent_strlen = 0; /* Strings start at offset 0. */
hp->cth_cuname = oldhp->cth_cuname;
hp->cth_parname = oldhp->cth_parname;
hp->cth_parlabel = oldhp->cth_parlabel;
swap_thing (cth->cth_parlabel);
swap_thing (cth->cth_parname);
swap_thing (cth->cth_cuname);
+ swap_thing (cth->cth_parent_strlen);
swap_thing (cth->cth_objtoff);
swap_thing (cth->cth_funcoff);
swap_thing (cth->cth_objtidxoff);
const ctf_sect_t *strsect, int *errp)
{
const ctf_preamble_t *pp;
- size_t hdrsz = sizeof (ctf_header_t);
+ size_t hdrsz;
ctf_header_t *hp;
ctf_dict_t *fp;
int foreign_endian = 0;
return (ctf_set_open_errno (errp, ECTF_CORRUPT));
}
+ if ((hp->cth_parname != 0 && hp->cth_parname < hp->cth_parent_strlen)
+ || (hp->cth_cuname != 0 && hp->cth_cuname < hp->cth_parent_strlen))
+ {
+ ctf_err_warn (NULL, 0, ECTF_CORRUPT,
+ _("Parent dict or CU name string offsets "
+ "(at %x and %x, respectively) are themselves "
+ "within the parent (upper bound: %x), thus "
+ "unreachable.\n"), hp->cth_parname, hp->cth_cuname,
+ hp->cth_parent_strlen);
+ return (ctf_set_open_errno (errp, ECTF_CORRUPT));
+ }
+
/* Once everything is determined to be valid, attempt to decompress the CTF
data buffer if it is compressed, or copy it into new storage if it is not
compressed but needs endian-flipping. Otherwise we just put the data
assert (t == (unsigned char *) buf + sizeof (ctf_header_t) + hdr.cth_stroff);
/* Construct the final string table and fill out all the string refs with the
- final offsets. */
+ final offsets. At link time, before the strtab can be constructed, child
+ dicts also need their cth_parent_strlen header field updated to match the
+ parent's. (These are always newly-created dicts, so we don't need to worry
+ about the upgraded-from-v3 case, which must always retain a
+ cth_parent_strlen value of 0.) */
+
+ if ((fp->ctf_flags & LCTF_LINKING) && fp->ctf_parent)
+ fp->ctf_header->cth_parent_strlen = fp->ctf_parent->ctf_str[CTF_STRTAB_0].cts_len;
strtab = ctf_str_write_strtab (fp);
hdrp->cth_strlen = strtab->cts_len;
buf_size += hdrp->cth_strlen;
*bufsiz = buf_size;
+ hdrp->cth_parent_strlen = fp->ctf_header->cth_parent_strlen;
return buf;