summaryrefslogtreecommitdiffstats
path: root/cddl/contrib/opensolaris/tools/ctf/cvt/ctf.c
diff options
context:
space:
mode:
authorgonzo <gonzo@FreeBSD.org>2012-03-24 01:47:33 +0000
committergonzo <gonzo@FreeBSD.org>2012-03-24 01:47:33 +0000
commit58eb4eb2a1f6de2f39cfa02526945469e41fd4bc (patch)
treebba18b626b83a0cdc8aec22e05e2f67513f64bcd /cddl/contrib/opensolaris/tools/ctf/cvt/ctf.c
parentf53c9505e0055cd6039308597b82ec8005568266 (diff)
downloadFreeBSD-src-58eb4eb2a1f6de2f39cfa02526945469e41fd4bc.zip
FreeBSD-src-58eb4eb2a1f6de2f39cfa02526945469e41fd4bc.tar.gz
Maintain target's byte order for multi-byte fields in CTF structures.
CTF format is not cross-platform by design, e.g. it is not guaranteed that data generated by ctfconvert/ctfmerge on one architecture will be successfuly read on another. CTF structures are saved/restored using naive approach. Roughly it looks like: write(fd, &ctf_struct, sizeof(ctf_struct)) read(fd, &ctf_struct, sizeof(ctf_struct)) By sheer luck memory layout of all type-related CTF structures is the same on amd64/i386/mips32/mips64. It's different on ARM though. sparc, ia64, powerpc, and powerpc64 were not tested. So in order to get file compatible with dtrace on ARM it should be compiled on ARM. Alternative solution would be to have "signatures" for every platform and ctfmerge should convert host's reperesentation of CTF structure to target's one using "signature" as template. This patch checks byte order of ELF files used for generating CTF record and makes sure that byte order of data written to resulting files is the same as target's byte order.
Diffstat (limited to 'cddl/contrib/opensolaris/tools/ctf/cvt/ctf.c')
-rw-r--r--cddl/contrib/opensolaris/tools/ctf/cvt/ctf.c99
1 files changed, 99 insertions, 0 deletions
diff --git a/cddl/contrib/opensolaris/tools/ctf/cvt/ctf.c b/cddl/contrib/opensolaris/tools/ctf/cvt/ctf.c
index e3ec1e1..55dd39e 100644
--- a/cddl/contrib/opensolaris/tools/ctf/cvt/ctf.c
+++ b/cddl/contrib/opensolaris/tools/ctf/cvt/ctf.c
@@ -62,6 +62,18 @@ struct ctf_buf {
int ntholes; /* number of type holes */
};
+/*
+ * Macros to reverse byte order
+ */
+#define BSWAP_8(x) ((x) & 0xff)
+#define BSWAP_16(x) ((BSWAP_8(x) << 8) | BSWAP_8((x) >> 8))
+#define BSWAP_32(x) ((BSWAP_16(x) << 16) | BSWAP_16((x) >> 16))
+
+#define SWAP_16(x) (x) = BSWAP_16(x)
+#define SWAP_32(x) (x) = BSWAP_32(x)
+
+static int target_requires_swap;
+
/*PRINTFLIKE1*/
static void
parseterminate(const char *fmt, ...)
@@ -140,6 +152,11 @@ write_label(void *arg1, void *arg2)
ctl.ctl_label = strtab_insert(&b->ctb_strtab, le->le_name);
ctl.ctl_typeidx = le->le_idx;
+ if (target_requires_swap) {
+ SWAP_32(ctl.ctl_label);
+ SWAP_32(ctl.ctl_typeidx);
+ }
+
ctf_buf_write(b, &ctl, sizeof (ctl));
return (1);
@@ -152,6 +169,10 @@ write_objects(iidesc_t *idp, ctf_buf_t *b)
ctf_buf_write(b, &id, sizeof (id));
+ if (target_requires_swap) {
+ SWAP_16(id);
+ }
+
debug(3, "Wrote object %s (%d)\n", (idp ? idp->ii_name : "(null)"), id);
}
@@ -180,10 +201,21 @@ write_functions(iidesc_t *idp, ctf_buf_t *b)
fdata[0] = CTF_TYPE_INFO(CTF_K_FUNCTION, 1, nargs);
fdata[1] = idp->ii_dtype->t_id;
+
+ if (target_requires_swap) {
+ SWAP_16(fdata[0]);
+ SWAP_16(fdata[1]);
+ }
+
ctf_buf_write(b, fdata, sizeof (fdata));
for (i = 0; i < idp->ii_nargs; i++) {
id = idp->ii_args[i]->t_id;
+
+ if (target_requires_swap) {
+ SWAP_16(id);
+ }
+
ctf_buf_write(b, &id, sizeof (id));
}
@@ -208,11 +240,25 @@ write_sized_type_rec(ctf_buf_t *b, ctf_type_t *ctt, size_t size)
ctt->ctt_size = CTF_LSIZE_SENT;
ctt->ctt_lsizehi = CTF_SIZE_TO_LSIZE_HI(size);
ctt->ctt_lsizelo = CTF_SIZE_TO_LSIZE_LO(size);
+ if (target_requires_swap) {
+ SWAP_32(ctt->ctt_name);
+ SWAP_16(ctt->ctt_info);
+ SWAP_16(ctt->ctt_size);
+ SWAP_32(ctt->ctt_lsizehi);
+ SWAP_32(ctt->ctt_lsizelo);
+ }
ctf_buf_write(b, ctt, sizeof (*ctt));
} else {
ctf_stype_t *cts = (ctf_stype_t *)ctt;
cts->ctt_size = (ushort_t)size;
+
+ if (target_requires_swap) {
+ SWAP_32(cts->ctt_name);
+ SWAP_16(cts->ctt_info);
+ SWAP_16(cts->ctt_size);
+ }
+
ctf_buf_write(b, cts, sizeof (*cts));
}
}
@@ -222,6 +268,12 @@ write_unsized_type_rec(ctf_buf_t *b, ctf_type_t *ctt)
{
ctf_stype_t *cts = (ctf_stype_t *)ctt;
+ if (target_requires_swap) {
+ SWAP_32(cts->ctt_name);
+ SWAP_16(cts->ctt_info);
+ SWAP_16(cts->ctt_size);
+ }
+
ctf_buf_write(b, cts, sizeof (*cts));
}
@@ -296,6 +348,9 @@ write_type(void *arg1, void *arg2)
encoding = ip->intr_fformat;
data = CTF_INT_DATA(encoding, ip->intr_offset, ip->intr_nbits);
+ if (target_requires_swap) {
+ SWAP_32(data);
+ }
ctf_buf_write(b, &data, sizeof (data));
break;
@@ -312,6 +367,11 @@ write_type(void *arg1, void *arg2)
cta.cta_contents = tp->t_ardef->ad_contents->t_id;
cta.cta_index = tp->t_ardef->ad_idxtype->t_id;
cta.cta_nelems = tp->t_ardef->ad_nelems;
+ if (target_requires_swap) {
+ SWAP_16(cta.cta_contents);
+ SWAP_16(cta.cta_index);
+ SWAP_32(cta.cta_nelems);
+ }
ctf_buf_write(b, &cta, sizeof (cta));
break;
@@ -341,6 +401,11 @@ write_type(void *arg1, void *arg2)
offset);
ctm.ctm_type = mp->ml_type->t_id;
ctm.ctm_offset = mp->ml_offset;
+ if (target_requires_swap) {
+ SWAP_32(ctm.ctm_name);
+ SWAP_16(ctm.ctm_type);
+ SWAP_16(ctm.ctm_offset);
+ }
ctf_buf_write(b, &ctm, sizeof (ctm));
}
} else {
@@ -355,6 +420,14 @@ write_type(void *arg1, void *arg2)
CTF_OFFSET_TO_LMEMHI(mp->ml_offset);
ctlm.ctlm_offsetlo =
CTF_OFFSET_TO_LMEMLO(mp->ml_offset);
+
+ if (target_requires_swap) {
+ SWAP_32(ctlm.ctlm_name);
+ SWAP_16(ctlm.ctlm_type);
+ SWAP_32(ctlm.ctlm_offsethi);
+ SWAP_32(ctlm.ctlm_offsetlo);
+ }
+
ctf_buf_write(b, &ctlm, sizeof (ctlm));
}
}
@@ -377,6 +450,12 @@ write_type(void *arg1, void *arg2)
offset = strtab_insert(&b->ctb_strtab, ep->el_name);
cte.cte_name = CTF_TYPE_NAME(CTF_STRTAB_0, offset);
cte.cte_value = ep->el_number;
+
+ if (target_requires_swap) {
+ SWAP_32(cte.cte_name);
+ SWAP_32(cte.cte_value);
+ }
+
ctf_buf_write(b, &cte, sizeof (cte));
i--;
}
@@ -420,6 +499,11 @@ write_type(void *arg1, void *arg2)
for (i = 0; i < (int) tp->t_fndef->fn_nargs; i++) {
id = tp->t_fndef->fn_args[i]->t_id;
+
+ if (target_requires_swap) {
+ SWAP_16(id);
+ }
+
ctf_buf_write(b, &id, sizeof (id));
}
@@ -613,6 +697,9 @@ ctf_gen(iiburst_t *iiburst, size_t *resszp, int do_compress)
int i;
+ target_requires_swap = do_compress & CTF_SWAP_BYTES;
+ do_compress &= ~CTF_SWAP_BYTES;
+
/*
* Prepare the header, and create the CTF output buffers. The data
* object section and function section are both lists of 2-byte
@@ -649,6 +736,18 @@ ctf_gen(iiburst_t *iiburst, size_t *resszp, int do_compress)
h.cth_stroff = ctf_buf_cur(buf);
h.cth_strlen = strtab_size(&buf->ctb_strtab);
+ if (target_requires_swap) {
+ SWAP_16(h.cth_preamble.ctp_magic);
+ SWAP_32(h.cth_parlabel);
+ SWAP_32(h.cth_parname);
+ SWAP_32(h.cth_lbloff);
+ SWAP_32(h.cth_objtoff);
+ SWAP_32(h.cth_funcoff);
+ SWAP_32(h.cth_typeoff);
+ SWAP_32(h.cth_stroff);
+ SWAP_32(h.cth_strlen);
+ }
+
/*
* We only do compression for ctfmerge, as ctfconvert is only
* supposed to be used on intermediary build objects. This is
OpenPOWER on IntegriCloud