Author: gonzo
Date: Sat Mar 24 01:47:33 2012
New Revision: 233407
URL: http://svn.freebsd.org/changeset/base/233407

Log:
  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.

Modified:
  head/cddl/contrib/opensolaris/tools/ctf/cvt/ctf.c
  head/cddl/contrib/opensolaris/tools/ctf/cvt/ctfmerge.c
  head/cddl/contrib/opensolaris/tools/ctf/cvt/ctftools.h
  head/cddl/contrib/opensolaris/tools/ctf/cvt/output.c

Modified: head/cddl/contrib/opensolaris/tools/ctf/cvt/ctf.c
==============================================================================
--- head/cddl/contrib/opensolaris/tools/ctf/cvt/ctf.c   Sat Mar 24 01:02:03 
2012        (r233406)
+++ head/cddl/contrib/opensolaris/tools/ctf/cvt/ctf.c   Sat Mar 24 01:47:33 
2012        (r233407)
@@ -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 *
 
        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
 
        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_t
                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
 {
        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 *ress
 
        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 *ress
        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

Modified: head/cddl/contrib/opensolaris/tools/ctf/cvt/ctfmerge.c
==============================================================================
--- head/cddl/contrib/opensolaris/tools/ctf/cvt/ctfmerge.c      Sat Mar 24 
01:02:03 2012        (r233406)
+++ head/cddl/contrib/opensolaris/tools/ctf/cvt/ctfmerge.c      Sat Mar 24 
01:47:33 2012        (r233407)
@@ -620,7 +620,7 @@ copy_ctf_data(char *srcfile, char *destf
                terminate("No CTF data found in source file %s\n", srcfile);
 
        tmpname = mktmpname(destfile, ".ctf");
-       write_ctf(srctd, destfile, tmpname, CTF_COMPRESS | keep_stabs);
+       write_ctf(srctd, destfile, tmpname, CTF_COMPRESS | CTF_SWAP_BYTES | 
keep_stabs);
        if (rename(tmpname, destfile) != 0) {
                terminate("Couldn't rename temp file %s to %s", tmpname,
                    destfile);
@@ -1015,7 +1015,7 @@ main(int argc, char **argv)
 
        tmpname = mktmpname(outfile, ".ctf");
        write_ctf(savetd, outfile, tmpname,
-           CTF_COMPRESS | write_fuzzy_match | dynsym | keep_stabs);
+           CTF_COMPRESS | CTF_SWAP_BYTES | write_fuzzy_match | dynsym | 
keep_stabs);
        if (rename(tmpname, outfile) != 0)
                terminate("Couldn't rename output temp file %s", tmpname);
        free(tmpname);

Modified: head/cddl/contrib/opensolaris/tools/ctf/cvt/ctftools.h
==============================================================================
--- head/cddl/contrib/opensolaris/tools/ctf/cvt/ctftools.h      Sat Mar 24 
01:02:03 2012        (r233406)
+++ head/cddl/contrib/opensolaris/tools/ctf/cvt/ctftools.h      Sat Mar 24 
01:47:33 2012        (r233407)
@@ -391,6 +391,7 @@ void merge_into_master(tdata_t *, tdata_
 #define        CTF_USE_DYNSYM  0x2 /* use .dynsym not .symtab */
 #define        CTF_COMPRESS    0x4 /* compress CTF output */
 #define        CTF_KEEP_STABS  0x8 /* keep .stabs sections */
+#define        CTF_SWAP_BYTES  0x10 /* target byte order is different from 
host */
 
 void write_ctf(tdata_t *, const char *, const char *, int);
 

Modified: head/cddl/contrib/opensolaris/tools/ctf/cvt/output.c
==============================================================================
--- head/cddl/contrib/opensolaris/tools/ctf/cvt/output.c        Sat Mar 24 
01:02:03 2012        (r233406)
+++ head/cddl/contrib/opensolaris/tools/ctf/cvt/output.c        Sat Mar 24 
01:47:33 2012        (r233407)
@@ -717,7 +717,7 @@ make_ctf_data(tdata_t *td, Elf *elf, con
 
        iiburst = sort_iidescs(elf, file, td, flags & CTF_FUZZY_MATCH,
            flags & CTF_USE_DYNSYM);
-       data = ctf_gen(iiburst, lenp, flags & CTF_COMPRESS);
+       data = ctf_gen(iiburst, lenp, flags & (CTF_COMPRESS |  CTF_SWAP_BYTES));
 
        iiburst_free(iiburst);
 
@@ -730,10 +730,12 @@ write_ctf(tdata_t *td, const char *curna
        struct stat st;
        Elf *elf = NULL;
        Elf *telf = NULL;
+       GElf_Ehdr ehdr;
        caddr_t data;
        size_t len;
        int fd = -1;
        int tfd = -1;
+       int byteorder;
 
        (void) elf_version(EV_CURRENT);
        if ((fd = open(curname, O_RDONLY)) < 0 || fstat(fd, &st) < 0)
@@ -746,6 +748,22 @@ write_ctf(tdata_t *td, const char *curna
        if ((telf = elf_begin(tfd, ELF_C_WRITE, NULL)) == NULL)
                elfterminate(curname, "Cannot write");
 
+       if (gelf_getehdr(elf, &ehdr)) {
+#if BYTE_ORDER == _BIG_ENDIAN
+               byteorder = ELFDATA2MSB;
+#else
+               byteorder = ELFDATA2LSB;
+#endif
+               /*
+                * If target and host has the same byte order
+                * clear byte swapping request
+                */
+               if  (ehdr.e_ident[EI_DATA] == byteorder)
+                       flags &= ~CTF_SWAP_BYTES;
+       }
+       else 
+               elfterminate(curname, "Failed to get EHDR");
+
        data = make_ctf_data(td, elf, curname, &len, flags);
        write_file(elf, curname, telf, newname, data, len, flags);
        free(data);
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to