From owner-freebsd-hackers@FreeBSD.ORG Thu Mar 14 10:29:55 2013 Return-Path: Delivered-To: freebsd-hackers@FreeBSD.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by hub.freebsd.org (Postfix) with ESMTP id 2973A407; Thu, 14 Mar 2013 10:29:55 +0000 (UTC) (envelope-from avg@FreeBSD.org) Received: from citadel.icyb.net.ua (citadel.icyb.net.ua [212.40.38.140]) by mx1.freebsd.org (Postfix) with ESMTP id EB89D113; Thu, 14 Mar 2013 10:29:53 +0000 (UTC) Received: from porto.starpoint.kiev.ua (porto-e.starpoint.kiev.ua [212.40.38.100]) by citadel.icyb.net.ua (8.8.8p3/ICyb-2.3exp) with ESMTP id MAA12823; Thu, 14 Mar 2013 12:29:45 +0200 (EET) (envelope-from avg@FreeBSD.org) Received: from localhost ([127.0.0.1]) by porto.starpoint.kiev.ua with esmtp (Exim 4.34 (FreeBSD)) id 1UG5Pt-000Jeh-0Z; Thu, 14 Mar 2013 12:29:45 +0200 Message-ID: <5141A695.8060905@FreeBSD.org> Date: Thu, 14 Mar 2013 12:29:41 +0200 From: Andriy Gapon User-Agent: Mozilla/5.0 (X11; FreeBSD amd64; rv:17.0) Gecko/20130220 Thunderbird/17.0.3 MIME-Version: 1.0 To: freebsd-hackers Subject: Re: dtrace: operands have incompatible types: "dmu_buf_t **" = "dmu_buf_t **" References: <513F385B.9010106@FreeBSD.org> In-Reply-To: <513F385B.9010106@FreeBSD.org> X-Enigmail-Version: 1.5.1 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 14 Mar 2013 10:29:55 -0000 First, this link http://docs.oracle.com/cd/E37670_01/E38608/html/dt_typcondef_dlang.html has a rather good description in section 2.13.4 of how types are managed in DTrace and of the special "C" and "D" namespaces/modules. on 12/03/2013 16:14 Andriy Gapon said the following: > > For your amusement: > > ============= testcase.d ============= > dmu_buf_t **buf; CTF data in my kernel contains these types: <1964> STRUCT dmu_buf (32 bytes) <1965> TYPEDEF dmu_buf_t refers to 1964 <1966> POINTER __anon__ refers to 1965 [2501] POINTER __anon__ refers to 1966 Type 2501 is "dmu_buf_t **" and DTrace uses this type for 'buf'. > /* Remove the following line to defuse. */ > bpobj_t *bpobj; Now, there are the following types related to bpobj_t [*footnote]: <8775> STRUCT bpobj (80 bytes) <8776> TYPEDEF bpobj_t refers to 8775 but there is no type for POINTER that refers to 8776. So, as described in the referenced document, dtrace creates bpobj_t* type in the D module. For that it also has to copy bpobj_t and struct bpobj types and also types for each member in struct bpobj and so on. As a result, copies of struct dmu_buf and typedef dmu_buf_t are also created in D namespace. These copied types have different type IDs, but all other of their properties are supposed to be such that the CTF handling code should be able to determine that the copies and the originals are equivalent types. > fbt::dmu_bonus_hold:entry > { > buf = args[3]; /* the error is about this line */ > } When DTrace resolves types for arguments of 'dmu_bonus_hold' it first looks in C and D namespaces and only then it looks in the kernel CTF data. So, now "dmu_buf_t **" is resolved to a copy of the original type. Unfortunately, there is a quirk that may lead to an error like incompatible types "dmu_buf_t **" and "dmu_buf_t **". The CTF code assumes that the types like a pointer to another type or a qualifier plus another type are always anonymous. And in fact they are in C language (note that I am talking about "raw" things like char* or const int, and not about typedefs). Also, the DWARF specification mandates that anonymous types either should not have a name attribute at all or its value should be an empty string (a single zero byte). For the above reasons, when the CTF code creates a copy of a type such as a pointer to another type, it simply sets a name of the copy to an empty string. And here is the quirk: in a violation of the DWARF specification our libdwarf sets names of all anonymous types to "__anon__". This name surely looks special to a human, but unfortunately there is nothing special about it to the code. In the end, the original type with "__anon__" name and the copied type with empty name are no longer considered to be equivalent. The following patch seems to resolve the problem: --- a/lib/libdwarf/dwarf_die.c +++ b/lib/libdwarf/dwarf_die.c @@ -29,8 +29,6 @@ #include #include "_libdwarf.h" -static const char *anon_name = "__anon__"; - int dwarf_die_add(Dwarf_CU cu, int level, uint64_t offset, uint64_t abnum, Dwarf_Abbrev a, Dwarf_Die *diep, Dwarf_Error *err) { @@ -57,7 +55,7 @@ dwarf_die_add(Dwarf_CU cu, int level, uint64_t offset, uint64_t abnum, Dwarf_Abb die->die_abnum = abnum; die->die_a = a; die->die_cu = cu; - die->die_name = anon_name; + die->die_name = ""; /* Initialise the list of attribute values. */ STAILQ_INIT(&die->die_attrval); [*footnote] In fact I see that for some, unknown to me, reason there are more than one entries for struct bpobj and typedef bpobj_t in the ctf data. For one of those entries there is a related bpobj_t pointer entry. But as far as I can tell from the code, it's always the last entry with a given name that is actually used as a type definition for that name. -- Andriy Gapon