Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 29 Mar 2014 17:18:23 +0000 (UTC)
From:      Dimitry Andric <dim@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-9@freebsd.org
Subject:   svn commit: r263915 - in stable: 10/cddl/contrib/opensolaris/tools/ctf/cvt 9/cddl/contrib/opensolaris/tools/ctf/cvt
Message-ID:  <201403291718.s2THINd9087355@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: dim
Date: Sat Mar 29 17:18:23 2014
New Revision: 263915
URL: http://svnweb.freebsd.org/changeset/base/263915

Log:
  MFC r260880 (by kaiw, from projects/elftoolchain):
  
    * Make die_mem_offset() be able to handle DW_AT_data_member_location
      attributes generated by Clang 3.4.
    * Document how different compilers generate DW_AT_data_member_location
      attributes differently.
    * Document the quirks about DW_FORM_data[48].
  
  This is a slightly modified version, adapted to work with the old
  libdwarf in stable/9 and stable/10.  It should fix DTrace on these
  branches, when the kernel is compiled with clang 3.4.
  
  Note that you have to build *and* install the CTF tools first, before
  building the kernel.  Otherwise you can possibly still get error
  messages similar to "failed to copy type of 'pr_uid': Type information
  is in parent and unavailable", when attempting to run dtrace(1).
  
  Submitted by:	kaiw

Modified:
  stable/9/cddl/contrib/opensolaris/tools/ctf/cvt/dwarf.c
Directory Properties:
  stable/9/cddl/contrib/opensolaris/   (props changed)

Changes in other areas also in this revision:
Modified:
  stable/10/cddl/contrib/opensolaris/tools/ctf/cvt/dwarf.c
Directory Properties:
  stable/10/   (props changed)

Modified: stable/9/cddl/contrib/opensolaris/tools/ctf/cvt/dwarf.c
==============================================================================
--- stable/9/cddl/contrib/opensolaris/tools/ctf/cvt/dwarf.c	Sat Mar 29 14:35:36 2014	(r263914)
+++ stable/9/cddl/contrib/opensolaris/tools/ctf/cvt/dwarf.c	Sat Mar 29 17:18:23 2014	(r263915)
@@ -489,16 +489,59 @@ die_mem_offset(dwarf_t *dw, Dwarf_Die di
 {
 	Dwarf_Locdesc *loc = NULL;
 	Dwarf_Signed locnum = 0;
+	Dwarf_Attribute at;
+	Dwarf_Half form;
 
-	if (dwarf_locdesc(die, name, &loc, &locnum, &dw->dw_err) != DW_DLV_OK)
+	if (name != DW_AT_data_member_location)
+		terminate("die %llu: can only process attribute "
+		    "DW_AT_data_member_location\n", die_off(dw, die));
+
+	if ((at = die_attr(dw, die, name, 0)) == NULL)
 		return (0);
 
-	if (locnum != 1 || loc->ld_s->lr_atom != DW_OP_plus_uconst) {
-		terminate("die %llu: cannot parse member offset\n",
-		    die_off(dw, die));
-	}
+	if (dwarf_whatform(at, &form, &dw->dw_err) != DW_DLV_OK)
+		return (0);
 
-	*valp = loc->ld_s->lr_number;
+	switch (form) {
+	case DW_FORM_block:
+	case DW_FORM_block1:
+	case DW_FORM_block2:
+	case DW_FORM_block4:
+		/*
+		 * GCC in base and Clang (3.3 or below) generates
+		 * DW_AT_data_member_location attribute with DW_FORM_block*
+		 * form. The attribute contains one DW_OP_plus_uconst
+		 * operator. The member offset stores in the operand.
+		 */
+		if (dwarf_locdesc(die, name, &loc, &locnum, &dw->dw_err) !=
+		    DW_DLV_OK)
+			return (0);
+		if (locnum != 1 || loc->ld_s->lr_atom != DW_OP_plus_uconst) {
+			terminate("die %llu: cannot parse member offset\n",
+			    die_off(dw, die));
+		}
+		*valp = loc->ld_s->lr_number;
+		break;
+
+	case DW_FORM_data1:
+	case DW_FORM_data2:
+	case DW_FORM_data4:
+	case DW_FORM_data8:
+	case DW_FORM_udata:
+		/*
+		 * Clang 3.4 generates DW_AT_data_member_location attribute
+		 * with DW_FORM_data* form (constant class). The attribute
+		 * stores a contant value which is the member offset.
+		 */
+		if (dwarf_attrval_unsigned(die, name, valp, &dw->dw_err) !=
+		    DW_DLV_OK)
+			return (0);
+		break;
+
+	default:
+		terminate("die %llu: cannot parse member offset with form "
+		    "%u\n", die_off(dw, die), form);
+	}
 
 	if (loc != NULL)
 		if (dwarf_locdesc_free(loc, &dw->dw_err) != DW_DLV_OK)
@@ -872,6 +915,9 @@ die_sou_create(dwarf_t *dw, Dwarf_Die st
     int type, const char *typename)
 {
 	Dwarf_Unsigned sz, bitsz, bitoff;
+#if BYTE_ORDER == _LITTLE_ENDIAN
+	Dwarf_Unsigned bysz;
+#endif
 	Dwarf_Die mem;
 	mlist_t *ml, **mlastp;
 	iidesc_t *ii;
@@ -944,8 +990,26 @@ die_sou_create(dwarf_t *dw, Dwarf_Die st
 #if BYTE_ORDER == _BIG_ENDIAN
 			ml->ml_offset += bitoff;
 #else
-			ml->ml_offset += tdesc_bitsize(ml->ml_type) - bitoff -
-			    ml->ml_size;
+			/*
+			 * Note that Clang 3.4 will sometimes generate
+			 * member DIE before generating the DIE for the
+			 * member's type. The code can not handle this
+			 * properly so that tdesc_bitsize(ml->ml_type) will
+			 * return 0 because ml->ml_type is unknown. As a
+			 * result, a wrong member offset will be calculated.
+			 * To workaround this, we can instead try to
+			 * retrieve the value of DW_AT_byte_size attribute
+			 * which stores the byte size of the space occupied
+			 * by the type. If this attribute exists, its value
+			 * should equal to tdesc_bitsize(ml->ml_type)/NBBY.
+			 */
+			if (die_unsigned(dw, mem, DW_AT_byte_size, &bysz, 0) &&
+			    bysz > 0)
+				ml->ml_offset += bysz * NBBY - bitoff -
+					ml->ml_size;
+			else
+				ml->ml_offset += tdesc_bitsize(ml->ml_type) -
+					bitoff - ml->ml_size;
 #endif
 		}
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201403291718.s2THINd9087355>