From patchwork Mon Jun 10 22:29:32 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andrew Burgess X-Patchwork-Id: 33079 Received: (qmail 59955 invoked by alias); 10 Jun 2019 22:29:41 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 59880 invoked by uid 89); 10 Jun 2019 22:29:41 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-25.2 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, RCVD_IN_DNSWL_NONE, SPF_PASS autolearn=ham version=3.3.1 spammy=reliance, flip, prop, wondered X-HELO: mail-wm1-f44.google.com Received: from mail-wm1-f44.google.com (HELO mail-wm1-f44.google.com) (209.85.128.44) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Mon, 10 Jun 2019 22:29:36 +0000 Received: by mail-wm1-f44.google.com with SMTP id c66so874405wmf.0 for ; Mon, 10 Jun 2019 15:29:36 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=embecosm.com; s=google; h=date:from:to:cc:subject:message-id:references:mime-version :content-disposition:in-reply-to:user-agent; bh=pBfruAhZ6Wt2lk2o2f4XcSi/rK1kokoQf9OA9ixUxc8=; b=WUrCsIxf509s10yAslS+5IZ/nMaT789sOxItpmvgHMfQgv8qm/H1zipIPPBxCFMGuf cIG3iYin119jAJEoN7hqVf41W17bSo3QtCJwStTbQjDopMiLAgBPsmmfZBQqzPZFfEVY FBe4P58XNugQTluPI7ZKqYUrlygPWpQ+B9kVkiXo+CzdsT8ZNH/3DXQS4pczGIRn1Ysw i4VWUxwwsVYhitIPVpV8SFIosxi8ExWGzcaLvTeuF8IxyTl5IhxA7EsDB9WYEoZ7mvrR o6CsWs/p8t/CJNoH3RX/nAr2KWrW0kZsyIOqUvlsX2dgKXslQlIVjFvpgtdOZarHOmAC vq0w== Return-Path: Received: from localhost (host86-180-62-212.range86-180.btcentralplus.com. [86.180.62.212]) by smtp.gmail.com with ESMTPSA id i188sm107587wma.27.2019.06.10.15.29.32 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Mon, 10 Jun 2019 15:29:32 -0700 (PDT) Date: Mon, 10 Jun 2019 23:29:32 +0100 From: Andrew Burgess To: Tom Tromey Cc: gdb-patches@sourceware.org Subject: Re: [PATCHv2 4/5] gdb: Carry default property type around with dynamic properties Message-ID: <20190610222931.GP23204@embecosm.com> References: <3a2c023242f902483cfdaaac9c99f1562534de7a.1557439866.git.andrew.burgess@embecosm.com> <87pnoacnsj.fsf@tromey.com> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <87pnoacnsj.fsf@tromey.com> X-Fortune: PEGGY FLEMMING is stealing BASKET BALLS to feed the babies in VERMONT. X-Editor: GNU Emacs [ http://www.gnu.org/software/emacs ] User-Agent: Mutt/1.9.2 (2017-12-15) X-IsSubscribed: yes * Tom Tromey [2019-05-22 15:05:48 -0400]: > Andrew> <1>: Abbrev Number: 12 (DW_TAG_array_type) > Andrew> DW_AT_data_location: 2 byte block: 97 6 (DW_OP_push_object_address; DW_OP_deref) > Andrew> DW_AT_allocated : 4 byte block: 97 6 30 2e (DW_OP_push_object_address; DW_OP_deref; DW_OP_lit0; DW_OP_ne) > Andrew> DW_AT_type : <0x2a> > Andrew> <2>: Abbrev Number: 13 (DW_TAG_subrange_type) > Andrew> DW_AT_lower_bound : 4 byte block: 97 23 10 6 (DW_OP_push_object_address; DW_OP_plus_uconst: 16; DW_OP_deref) > Andrew> DW_AT_upper_bound : 4 byte block: 97 23 14 6 (DW_OP_push_object_address; DW_OP_plus_uconst: 20; DW_OP_deref) > Andrew> DW_AT_byte_stride : 6 byte block: 97 23 c 6 34 1e (DW_OP_push_object_address; DW_OP_plus_uconst: 12; DW_OP_deref; DW_OP_lit4; DW_OP_mul) > > This is a funny coincidence, because we were discussing a similar case > with Ada just this week. Gnat can generate very similar expressions in > some cases: > > <1><11b5>: Abbrev Number: 8 (DW_TAG_array_type) > <11b6> DW_AT_name : (indirect string, offset: 0x1ba2): string > <11ba> DW_AT_data_location: 2 byte block: 97 6 (DW_OP_push_object_address; DW_OP_deref) > <11bd> DW_AT_type : <0x113c> > <11c1> DW_AT_sibling : <0x11db> > <2><11c5>: Abbrev Number: 9 (DW_TAG_subrange_type) > <11c6> DW_AT_type : <0x11e0> > <11ca> DW_AT_lower_bound : 6 byte block: 97 23 8 6 94 4 (DW_OP_push_object_address; DW_OP_plus_uconst: 8; DW_OP_deref; DW_OP_deref_size: 4) > <11d1> DW_AT_upper_bound : 8 byte block: 97 23 8 6 23 4 94 4 (DW_OP_push_object_address; DW_OP_plus_uconst: 8; DW_OP_deref; DW_OP_plus_uconst: 4; DW_OP_deref_size: 4) > > > Essentially what's going on here is that the compiler represents a > pointer-to-array as a structure that holds a pointer and the array > bounds; and then chooses to represent this in DWARF as the above. > > This in turn causes problems in gdb. In the above case, it's not > possible to make a call like `do_something("string")', because gdb > doesn't know that constructing one of these arrays at runtime actually > requires two allocations and some special messing around. > > So, this week we've been talking about changing the representation of > these things to be more explicit, that is, make the hidden struct type > explicit (and marked DW_AT_artificial). > > I wonder how Fortran will handle this, or whether it even needs to. Is > it possible for gdb to construct one of these arrays at runtime? > > Another option, besides changing the representation, would be to teach > gdb how to create one of the above by recognizing the expressions as a > kind of special case. This seemed uglier and more fragile, though. > > For Ada at least, this sort of DWARF isn't the default yet. The default > is this Ada-specific name encodings scheme; you have to opt-in to DWARF > using a compiler command-line flag; but one of the things I'm looking > into is getting gdb to the point where we can flip the default. > > Andrew> I wonder if the best solution for dealing with signed properties will > Andrew> be to move away from an over reliance on fetch_address, and instead > Andrew> come up with a new solution that considers the current type of the > Andrew> value on the stack, and the type that the value needs to become; > Andrew> basically a solution built around casting rather than assuming we > Andrew> always want an address. > > DWARF now has typed expressions as well, so gcc could just emit this > explicitly, I think. I didn't look at gcc's dwarf2out.c for this but > maybe you need -gdwarf-5 to make this happen. I've seen the typed expressions, but my immediate focus is on debugging GCC's default DWARF as that's what most folk seem to end up debugging with. > > Andrew> It is my belief that we can find a suitable default type for every > Andrew> dynamic property, either specified explicitly in the DWARF spec, or we > Andrew> can infer an obvious choice if the spec doesn't help us. > > Seems reasonable. > > Andrew> +static struct type * > Andrew> +dwarf2_per_cu_addr_sized_int_type (struct dwarf2_per_cu_data *per_cu) > Andrew> +{ > Andrew> + struct objfile *objfile = per_cu->dwarf2_per_objfile->objfile; > Andrew> + int addr_size = dwarf2_per_cu_addr_size (per_cu); > Andrew> + struct type *int_type; > Andrew> + > Andrew> + int_type = objfile_type (objfile)->builtin_short; > Andrew> + if (int_type != NULL && TYPE_LENGTH (int_type) == addr_size) > Andrew> + return int_type; > > dwarf2_per_cu_addr_type handles unsigned char here, but this one does not. > I doubt it matters but I wonder why the difference. In the places where this is used the DWARF standard specifies that the property is signed, so there was no need to handle unsigned. > > Andrew> +/* Return a type that is a generic pointer type, the size of which matches > Andrew> + the address size given in the compilation unit header for PER_CU. */ > Andrew> +static struct type * > Andrew> +dwarf2_per_cu_addr_type (struct dwarf2_per_cu_data *per_cu) > Andrew> +{ > Andrew> + struct objfile *objfile = per_cu->dwarf2_per_objfile->objfile; > Andrew> + struct type *void_type = objfile_type (objfile)->builtin_void; > Andrew> + struct type *addr_type = lookup_pointer_type (void_type); > Andrew> + int addr_size = dwarf2_per_cu_addr_size (per_cu); > Andrew> + > Andrew> + if (TYPE_LENGTH (addr_type) == addr_size) > Andrew> + return addr_type; > Andrew> + > Andrew> + /* Yuck! We currently only support one address size per architecture in > Andrew> + GDB, which should usually match the address size encoded into the > Andrew> + compilation unit header. However... we have a few tests where this is > Andrew> + not the case, these are mostly test cases where the DWARF is hand > Andrew> + written and includes a fixed address size, for example 8-bytes. When > Andrew> + we compile these tests on a 32-bit i386 target the gdbarch address > Andrew> + size is 4-bytes and the above attempt to create a suitable address > Andrew> + type fails. > Andrew> + > Andrew> + As we can't currently create an address type of a different size, we > Andrew> + instead substitute an unsigned integer for an address. > Andrew> + > Andrew> + I don't know if there are targets that have signed addresses and if > Andrew> + they would need a signed integer here. I figure we'll handle that > Andrew> + case when it presents itself as a problem. */ > > gdbarch.sh makes a distinction between addresses and pointers which, I > confess, I have never understood. However, based on this, I think at > least MIPS may have signed pointers. From mips-tdep.c: > > set_gdbarch_pointer_to_address (gdbarch, signed_pointer_to_address); > set_gdbarch_address_to_pointer (gdbarch, address_to_signed_pointer); I've extended dwarf2_per_cu_addr_sized_int_type to create signed or unsigned types, and made dwarf2_per_cu_addr_type use this, taking the sign of the default 'void *' type into account. This should mean that MIPS will do the right thing now. > > Also, I wonder whether it wouldn't be simpler to just provide a way to > create a TYPE_CODE_PTR type with a specified size. I wondered about that, but I was worried that it might open a huge can of worms that I'd rather not open. If we did add multiple pointer sizes later then it's easy to just change dwarf2_per_cu_addr_type to do the right thing I think. How would you feel with this version? Thanks, Andrew --- commit 191bf42d636a33c374dbe0b65eb53b7950e49f48 Author: Andrew Burgess Date: Wed May 8 13:16:03 2019 +0100 gdb: Carry default property type around with dynamic properties This commit is preparation for the next one, with the aim of better supporting signed dynamic properties on targets where the address size specified in the DWARF headers is smaller than a CORE_ADDR, for example debugging an i386 application on x86-64. Consider this small Fortran program 'bounds.f90': program test integer, allocatable :: array (:) allocate (array (-5:5)) array(3) = 1 end program test Compiled with 'gfortran -m32 -g3 -O0 -o bounds bounds.f90'. The DWARF for 'array' looks like this: <2><97>: Abbrev Number: 10 (DW_TAG_variable) <98> DW_AT_name : (indirect string, offset: 0x0): array <9c> DW_AT_decl_file : 1 <9d> DW_AT_decl_line : 2 <9e> DW_AT_type : <0xaf> DW_AT_location : 2 byte block: 91 58 (DW_OP_fbreg: -40) <2>: Abbrev Number: 11 (DW_TAG_lexical_block) DW_AT_low_pc : 0x80485c3 DW_AT_high_pc : 0x8b <2>: Abbrev Number: 0 <1>: Abbrev Number: 12 (DW_TAG_array_type) DW_AT_data_location: 2 byte block: 97 6 (DW_OP_push_object_address; DW_OP_deref) DW_AT_allocated : 4 byte block: 97 6 30 2e (DW_OP_push_object_address; DW_OP_deref; DW_OP_lit0; DW_OP_ne) DW_AT_type : <0x2a> <2>: Abbrev Number: 13 (DW_TAG_subrange_type) DW_AT_lower_bound : 4 byte block: 97 23 10 6 (DW_OP_push_object_address; DW_OP_plus_uconst: 16; DW_OP_deref) DW_AT_upper_bound : 4 byte block: 97 23 14 6 (DW_OP_push_object_address; DW_OP_plus_uconst: 20; DW_OP_deref) DW_AT_byte_stride : 6 byte block: 97 23 c 6 34 1e (DW_OP_push_object_address; DW_OP_plus_uconst: 12; DW_OP_deref; DW_OP_lit4; DW_OP_mul) <2>: Abbrev Number: 0 If we look at the DW_AT_lower_bound attribute, which will become a dynamic property that GDB evaluates when needed by calling dwarf2_evaluate_property. The process of evaluating a dynamic property requires GDB to execute each DW_OP_* operation, the results of these operations is held on a stack of 'struct value *'s. When the entire expression is evaluated the result is on top of the stack. If we look at DW_AT_lower_bound then the last operation is DW_OP_deref, this loads a signed address the size of which matches the DWARF address size, and so in our i386 on x86-64 situation, the top of the stack will be a signed 4-byte value. The problem is how these values are fetched from the stack. Currently they are always fetched by a call to dwarf_expr_context::fetch_address, which converts the value to an unsigned value with a length matching the values current length, before converting to a CORE_ADDR. This means we loose the signed nature of the property. I wonder if the best solution for dealing with signed properties will be to move away from an over reliance on fetch_address, and instead come up with a new solution that considers the current type of the value on the stack, and the type that the value needs to become; basically a solution built around casting rather than assuming we always want an address. However, before we can start to even think about moving away from fetch_address, there is a more urgent issue to fix, which is we don't currently know what type each property should be. We just hold the value of the property in a CORE_ADDR as returned by fetch_address, and rely on higher level code (outside of the DWARF expression evaluation code) to fix things up for us. This is what this patch aims to address. When creating a dynamic property (see attr_to_dynamic_prop in dwarf2read.c) we can sometimes figure out the type of a property; if the property is a reference to another DIE then it will have a DW_AT_type attribute. However, the DW_AT_lower_bound case above isn't a reference to another DIE, it's just a DWARF expression. We don't have any indication for what type the property should have. Luckily, the DWARF spec helps us out, for the lower and upper bounds 5.13 of the DWARFv5 spec tells us that without any other type information the bounds are signed integers the same size as a DWARF address. It is my belief that we can find a suitable default type for every dynamic property, either specified explicitly in the DWARF spec, or we can infer an obvious choice if the spec doesn't help us. This commit extends the creation of all dynamic properties to include suggesting a suitable default type, all dynamic properties now always carry their type around with them. In later commits we can use this property type to ensure that the value we extract from the DWARF stack is handled in a suitable manor to correctly maintain its sign extension. There should be no user visible changes from this commit. The actual fix to correctly support negative array bounds will come later. gdb/ChangeLog: * dwarf2loc.c (dwarf2_evaluate_property): Update to take account of changes to field names, and use new is_reference field to decide if a property is a reference or not. * dwarf2loc.h (struct dwarf2_locexpr_baton): Add 'is_reference' field. (struct dwarf2_property_baton): Update header comment, rename 'referenced_type' to 'property_type' and update comments. * dwarf2read.c (attr_to_dynamic_prop): Add extra parameter to hold default property type, store in property baton, update to take accound of renamed field. (read_func_scope): Update call to attr_to_dynamic_prop. (read_array_type): Likewise. (dwarf2_per_cu_addr_sized_int_type): New function. (read_subrange_index_type): Move type finding code to dwarf2_per_cu_addr_sized_int_type. (read_subrange_type): Update calls to attr_to_dynamic_prop. (dwarf2_per_cu_addr_type): New function. (set_die_type): Update calls to attr_to_dynamic_prop. diff --git a/gdb/dwarf2loc.c b/gdb/dwarf2loc.c index c03f261f1e1..88d34eb8660 100644 --- a/gdb/dwarf2loc.c +++ b/gdb/dwarf2loc.c @@ -2443,15 +2443,15 @@ dwarf2_evaluate_property (const struct dynamic_prop *prop, { const struct dwarf2_property_baton *baton = (const struct dwarf2_property_baton *) prop->data.baton; + gdb_assert (baton->property_type != NULL); if (dwarf2_locexpr_baton_eval (&baton->locexpr, frame, addr_stack ? addr_stack->addr : 0, value)) { - if (baton->referenced_type) + if (baton->locexpr.is_reference) { - struct value *val = value_at (baton->referenced_type, *value); - + struct value *val = value_at (baton->property_type, *value); *value = value_as_address (val); } return true; @@ -2471,7 +2471,7 @@ dwarf2_evaluate_property (const struct dynamic_prop *prop, data = dwarf2_find_location_expression (&baton->loclist, &size, pc); if (data != NULL) { - val = dwarf2_evaluate_loc_desc (baton->referenced_type, frame, data, + val = dwarf2_evaluate_loc_desc (baton->property_type, frame, data, size, baton->loclist.per_cu); if (!value_optimized_out (val)) { @@ -2497,7 +2497,7 @@ dwarf2_evaluate_property (const struct dynamic_prop *prop, { /* This approach lets us avoid checking the qualifiers. */ if (TYPE_MAIN_TYPE (pinfo->type) - == TYPE_MAIN_TYPE (baton->referenced_type)) + == TYPE_MAIN_TYPE (baton->property_type)) break; } if (pinfo == NULL) diff --git a/gdb/dwarf2loc.h b/gdb/dwarf2loc.h index ac1a771a9f3..baa5762003d 100644 --- a/gdb/dwarf2loc.h +++ b/gdb/dwarf2loc.h @@ -183,6 +183,12 @@ struct dwarf2_locexpr_baton zero. */ size_t size; + /* When true this location expression is a reference and actually + describes the address at which the value of the attribute can be + found. When false the expression provides the value of the attribute + directly. */ + bool is_reference; + /* The compilation unit containing the symbol whose location we're computing. */ struct dwarf2_per_cu_data *per_cu; @@ -228,23 +234,27 @@ struct dwarf2_offset_baton /* A dynamic property is either expressed as a single location expression or a location list. If the property is an indirection, pointing to - another die, keep track of the targeted type in REFERENCED_TYPE. */ + another die, keep track of the targeted type in PROPERTY_TYPE. + Alternatively, if the property location gives the property value + directly then it will have PROPERTY_TYPE. */ struct dwarf2_property_baton { /* If the property is an indirection, we need to evaluate the location - in the context of the type REFERENCED_TYPE. - If NULL, the location is the actual value of the property. */ - struct type *referenced_type; + in the context of the type PROPERTY_TYPE. If the property is supplied + by value then it will be of PROPERTY_TYPE. This field should never be + NULL. */ + struct type *property_type; union { - /* Location expression. */ + /* Location expression either evaluated in the context of + PROPERTY_TYPE, or a value of type PROPERTY_TYPE. */ struct dwarf2_locexpr_baton locexpr; - /* Location list to be evaluated in the context of REFERENCED_TYPE. */ + /* Location list to be evaluated in the context of PROPERTY_TYPE. */ struct dwarf2_loclist_baton loclist; - /* The location is an offset to REFERENCED_TYPE. */ + /* The location is an offset to PROPERTY_TYPE. */ struct dwarf2_offset_baton offset_info; }; }; diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c index fc3d888fadc..e8d1e3ced18 100644 --- a/gdb/dwarf2read.c +++ b/gdb/dwarf2read.c @@ -1833,7 +1833,7 @@ static void read_signatured_type (struct signatured_type *); static int attr_to_dynamic_prop (const struct attribute *attr, struct die_info *die, struct dwarf2_cu *cu, - struct dynamic_prop *prop); + struct dynamic_prop *prop, struct type *type); /* memory allocation interface */ @@ -1913,6 +1913,10 @@ static void queue_comp_unit (struct dwarf2_per_cu_data *per_cu, static void process_queue (struct dwarf2_per_objfile *dwarf2_per_objfile); +static struct type *dwarf2_per_cu_addr_type (struct dwarf2_per_cu_data *per_cu); +static struct type *dwarf2_per_cu_addr_sized_int_type + (struct dwarf2_per_cu_data *per_cu, bool unsigned_p); + /* Class, the destructor of which frees all allocated queue entries. This will only have work to do if an error was thrown while processing the dwarf. If no error was thrown then the queue entries should have all @@ -13759,7 +13763,8 @@ read_func_scope (struct die_info *die, struct dwarf2_cu *cu) { newobj->static_link = XOBNEW (&objfile->objfile_obstack, struct dynamic_prop); - attr_to_dynamic_prop (attr, die, cu, newobj->static_link); + attr_to_dynamic_prop (attr, die, cu, newobj->static_link, + dwarf2_per_cu_addr_type (cu->per_cu)); } cu->list_in_scope = cu->get_builder ()->get_local_symbols (); @@ -16515,10 +16520,13 @@ read_array_type (struct die_info *die, struct dwarf2_cu *cu) if (attr != NULL) { int stride_ok; + struct type *prop_type + = dwarf2_per_cu_addr_sized_int_type (cu->per_cu, false); byte_stride_prop = (struct dynamic_prop *) alloca (sizeof (struct dynamic_prop)); - stride_ok = attr_to_dynamic_prop (attr, die, cu, byte_stride_prop); + stride_ok = attr_to_dynamic_prop (attr, die, cu, byte_stride_prop, + prop_type); if (!stride_ok) { complaint (_("unable to read array DW_AT_byte_stride " @@ -17733,22 +17741,26 @@ read_base_type (struct die_info *die, struct dwarf2_cu *cu) static int attr_to_dynamic_prop (const struct attribute *attr, struct die_info *die, - struct dwarf2_cu *cu, struct dynamic_prop *prop) + struct dwarf2_cu *cu, struct dynamic_prop *prop, + struct type *default_type) { struct dwarf2_property_baton *baton; struct obstack *obstack = &cu->per_cu->dwarf2_per_objfile->objfile->objfile_obstack; + gdb_assert (default_type != NULL); + if (attr == NULL || prop == NULL) return 0; if (attr_form_is_block (attr)) { baton = XOBNEW (obstack, struct dwarf2_property_baton); - baton->referenced_type = NULL; + baton->property_type = default_type; baton->locexpr.per_cu = cu->per_cu; baton->locexpr.size = DW_BLOCK (attr)->size; baton->locexpr.data = DW_BLOCK (attr)->data; + baton->locexpr.is_reference = false; prop->data.baton = baton; prop->kind = PROP_LOCEXPR; gdb_assert (prop->data.baton != NULL); @@ -17773,7 +17785,7 @@ attr_to_dynamic_prop (const struct attribute *attr, struct die_info *die, if (attr_form_is_section_offset (target_attr)) { baton = XOBNEW (obstack, struct dwarf2_property_baton); - baton->referenced_type = die_type (target_die, target_cu); + baton->property_type = die_type (target_die, target_cu); fill_in_loclist_baton (cu, &baton->loclist, target_attr); prop->data.baton = baton; prop->kind = PROP_LOCLIST; @@ -17782,10 +17794,11 @@ attr_to_dynamic_prop (const struct attribute *attr, struct die_info *die, else if (attr_form_is_block (target_attr)) { baton = XOBNEW (obstack, struct dwarf2_property_baton); - baton->referenced_type = die_type (target_die, target_cu); + baton->property_type = die_type (target_die, target_cu); baton->locexpr.per_cu = cu->per_cu; baton->locexpr.size = DW_BLOCK (target_attr)->size; baton->locexpr.data = DW_BLOCK (target_attr)->data; + baton->locexpr.is_reference = true; prop->data.baton = baton; prop->kind = PROP_LOCEXPR; gdb_assert (prop->data.baton != NULL); @@ -17806,7 +17819,7 @@ attr_to_dynamic_prop (const struct attribute *attr, struct die_info *die, return 0; baton = XOBNEW (obstack, struct dwarf2_property_baton); - baton->referenced_type = read_type_die (target_die->parent, + baton->property_type = read_type_die (target_die->parent, target_cu); baton->offset_info.offset = offset; baton->offset_info.type = die_type (target_die, target_cu); @@ -17831,6 +17844,37 @@ attr_to_dynamic_prop (const struct attribute *attr, struct die_info *die, return 1; } +/* Find an integer type the same size as the address size given in the + compilation unit header for PER_CU. UNSIGNED_P controls if the integer + is unsigned or not. */ + +static struct type * +dwarf2_per_cu_addr_sized_int_type (struct dwarf2_per_cu_data *per_cu, + bool unsigned_p) +{ + struct objfile *objfile = per_cu->dwarf2_per_objfile->objfile; + int addr_size = dwarf2_per_cu_addr_size (per_cu); + struct type *int_type; + + /* Helper macro to examine the various builtin types. */ +#define TRY_TYPE(F) \ + int_type = (unsigned_p \ + ? objfile_type (objfile)->builtin_unsigned_ ## F \ + : objfile_type (objfile)->builtin_ ## F); \ + if (int_type != NULL && TYPE_LENGTH (int_type) == addr_size) \ + return int_type + + TRY_TYPE (char); + TRY_TYPE (short); + TRY_TYPE (int); + TRY_TYPE (long); + TRY_TYPE (long_long); + +#undef TRY_TYPE + + gdb_assert_not_reached ("unable to find suitable integer type"); +} + /* Read the DW_AT_type attribute for a sub-range. If this attribute is not present (which is valid) then compute the default type based on the compilation units address size. */ @@ -17853,30 +17897,7 @@ read_subrange_index_type (struct die_info *die, struct dwarf2_cu *cu) FIXME: muller/2010-05-28: Possible references to object for low bound, high bound or count are not yet handled by this code. */ if (TYPE_CODE (index_type) == TYPE_CODE_VOID) - { - struct objfile *objfile = cu->per_cu->dwarf2_per_objfile->objfile; - struct gdbarch *gdbarch = get_objfile_arch (objfile); - int addr_size = gdbarch_addr_bit (gdbarch) /8; - struct type *int_type = objfile_type (objfile)->builtin_int; - - /* Test "int", "long int", and "long long int" objfile types, - and select the first one having a size above or equal to the - architecture address size. */ - if (int_type && TYPE_LENGTH (int_type) >= addr_size) - index_type = int_type; - else - { - int_type = objfile_type (objfile)->builtin_long; - if (int_type && TYPE_LENGTH (int_type) >= addr_size) - index_type = int_type; - else - { - int_type = objfile_type (objfile)->builtin_long_long; - if (int_type && TYPE_LENGTH (int_type) >= addr_size) - index_type = int_type; - } - } - } + index_type = dwarf2_per_cu_addr_sized_int_type (cu->per_cu, false); return index_type; } @@ -17945,7 +17966,7 @@ read_subrange_type (struct die_info *die, struct dwarf2_cu *cu) attr = dwarf2_attr (die, DW_AT_lower_bound, cu); if (attr) - attr_to_dynamic_prop (attr, die, cu, &low); + attr_to_dynamic_prop (attr, die, cu, &low, base_type); else if (!low_default_is_valid) complaint (_("Missing DW_AT_lower_bound " "- DIE at %s [in module %s]"), @@ -17954,10 +17975,10 @@ read_subrange_type (struct die_info *die, struct dwarf2_cu *cu) struct attribute *attr_ub, *attr_count; attr = attr_ub = dwarf2_attr (die, DW_AT_upper_bound, cu); - if (!attr_to_dynamic_prop (attr, die, cu, &high)) + if (!attr_to_dynamic_prop (attr, die, cu, &high, base_type)) { attr = attr_count = dwarf2_attr (die, DW_AT_count, cu); - if (attr_to_dynamic_prop (attr, die, cu, &high)) + if (attr_to_dynamic_prop (attr, die, cu, &high, base_type)) { /* If bounds are constant do the final calculation here. */ if (low.kind == PROP_CONST && high.kind == PROP_CONST) @@ -25310,6 +25331,24 @@ dwarf2_per_cu_text_offset (struct dwarf2_per_cu_data *per_cu) return ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); } +/* Return a type that is a generic pointer type, the size of which matches + the address size given in the compilation unit header for PER_CU. */ +static struct type * +dwarf2_per_cu_addr_type (struct dwarf2_per_cu_data *per_cu) +{ + struct objfile *objfile = per_cu->dwarf2_per_objfile->objfile; + struct type *void_type = objfile_type (objfile)->builtin_void; + struct type *addr_type = lookup_pointer_type (void_type); + int addr_size = dwarf2_per_cu_addr_size (per_cu); + + if (TYPE_LENGTH (addr_type) == addr_size) + return addr_type; + + addr_type + = dwarf2_per_cu_addr_sized_int_type (per_cu, TYPE_UNSIGNED (addr_type)); + return addr_type; +} + /* Return DWARF version number of PER_CU. */ short @@ -25576,7 +25615,9 @@ set_die_type (struct die_info *die, struct type *type, struct dwarf2_cu *cu) attr = dwarf2_attr (die, DW_AT_allocated, cu); if (attr_form_is_block (attr)) { - if (attr_to_dynamic_prop (attr, die, cu, &prop)) + struct type *prop_type + = dwarf2_per_cu_addr_sized_int_type (cu->per_cu, false); + if (attr_to_dynamic_prop (attr, die, cu, &prop, prop_type)) add_dyn_prop (DYN_PROP_ALLOCATED, prop, type); } else if (attr != NULL) @@ -25590,7 +25631,9 @@ set_die_type (struct die_info *die, struct type *type, struct dwarf2_cu *cu) attr = dwarf2_attr (die, DW_AT_associated, cu); if (attr_form_is_block (attr)) { - if (attr_to_dynamic_prop (attr, die, cu, &prop)) + struct type *prop_type + = dwarf2_per_cu_addr_sized_int_type (cu->per_cu, false); + if (attr_to_dynamic_prop (attr, die, cu, &prop, prop_type)) add_dyn_prop (DYN_PROP_ASSOCIATED, prop, type); } else if (attr != NULL) @@ -25602,7 +25645,8 @@ set_die_type (struct die_info *die, struct type *type, struct dwarf2_cu *cu) /* Read DW_AT_data_location and set in type. */ attr = dwarf2_attr (die, DW_AT_data_location, cu); - if (attr_to_dynamic_prop (attr, die, cu, &prop)) + if (attr_to_dynamic_prop (attr, die, cu, &prop, + dwarf2_per_cu_addr_type (cu->per_cu))) add_dyn_prop (DYN_PROP_DATA_LOCATION, prop, type); if (dwarf2_per_objfile->die_type_hash == NULL)