diff --git a/gdb/dwarf2loc.c b/gdb/dwarf2loc.c index 19902a9..4c56107 100644 --- a/gdb/dwarf2loc.c +++ b/gdb/dwarf2loc.c @@ -107,8 +107,8 @@ struct dwarf_expr_baton { struct frame_info *frame; struct objfile *objfile; - /* From DW_TAG_variable's DW_AT_location (not DW_TAG_type's - DW_AT_data_location) for DW_OP_push_object_address. */ + + /* Address to set by object_address_set. */ CORE_ADDR object_address; }; @@ -217,9 +217,12 @@ dwarf_expr_object_address (void *baton) return debaton->object_address; } -/* Address of the variable we are currently referring to. It is set from - DW_TAG_variable's DW_AT_location (not DW_TAG_type's DW_AT_data_location) for - DW_OP_push_object_address. */ +/* Address of the variable we are currently referring to. It is initially set + from DW_TAG_variable's DW_AT_location. It is used for + DW_OP_push_object_address. It is never the address derived by + DW_AT_data_location (nor completely unrelated DW_AT_data_member_location). + Expresses the address of the closes DW_AT_type, such as an element of an + array, not the base address of an array. */ static CORE_ADDR object_address; diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c index e559d86..8ce4884 100644 --- a/gdb/dwarf2read.c +++ b/gdb/dwarf2read.c @@ -4655,6 +4655,8 @@ create_single_array_dimension (struct type *type, struct type *range_type, validity while accessing FIELD_LOC_KIND_DWARF_BLOCK. */ fetch_die_type_attrs (die, range_type, cu); + finalize_type (type); + return type; } @@ -5095,6 +5097,7 @@ read_tag_string_type (struct die_info *die, struct dwarf2_cu *cu) struct type *type, *range_type, *index_type, *char_type; struct attribute *attr; int length; + char *name; index_type = builtin_type_int32; /* RANGE_TYPE is allocated from OBJFILE, not as a permanent type. */ @@ -5185,6 +5188,10 @@ read_tag_string_type (struct die_info *die, struct dwarf2_cu *cu) type = create_string_type (NULL, range_type); + name = dwarf2_name (die, cu); + if (name) + TYPE_NAME (type) = name; + return set_die_type (die, type, cu); } diff --git a/gdb/eval.c b/gdb/eval.c index 83ae2cd..6ae3cfa 100644 --- a/gdb/eval.c +++ b/gdb/eval.c @@ -2696,6 +2696,7 @@ evaluate_subexp_for_sizeof (struct expression *exp, int *pos) int pc; struct type *type; struct value *val; + struct cleanup *back_to; pc = (*pos); op = exp->elts[pc].opcode; @@ -2709,7 +2710,14 @@ evaluate_subexp_for_sizeof (struct expression *exp, int *pos) case UNOP_IND: (*pos)++; val = evaluate_subexp (NULL_TYPE, exp, pos, EVAL_AVOID_SIDE_EFFECTS); + + back_to = make_cleanup (null_cleanup, 0); + object_address_set (value_raw_address (val)); + type = check_typedef (value_type (val)); + + do_cleanups (back_to); + if (TYPE_CODE (type) != TYPE_CODE_PTR && TYPE_CODE (type) != TYPE_CODE_REF && TYPE_CODE (type) != TYPE_CODE_ARRAY) diff --git a/gdb/f-valprint.c b/gdb/f-valprint.c index 44456f8..35f875e 100644 --- a/gdb/f-valprint.c +++ b/gdb/f-valprint.c @@ -146,6 +146,7 @@ f77_create_arrayprint_offset_tbl (struct type *type, struct ui_file *stream) TYPE_ARRAY_BYTE_STRIDE_VALUE (tmp_type); tmp_type = TYPE_TARGET_TYPE (tmp_type); + CHECK_TYPEDEF (tmp_type); ndimen++; } diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c index ec32200..f84a20b 100644 --- a/gdb/gdbtypes.c +++ b/gdb/gdbtypes.c @@ -875,13 +875,18 @@ create_array_type (struct type *result_type, In such cases, the array length should be zero. TYPE_TARGET_STUB needs to be checked as it may have dependencies on DWARF blocks depending on runtime information not available during the CREATE_ARRAY_TYPE time. */ - if (high_bound < low_bound || TYPE_TARGET_STUB (element_type)) + if (high_bound < low_bound) + TYPE_LENGTH (result_type) = 0; + else if (TYPE_BYTE_STRIDE (range_type) > 0) + TYPE_LENGTH (result_type) = TYPE_BYTE_STRIDE (range_type) + * (high_bound - low_bound + 1); + else if (TYPE_TARGET_STUB (element_type)) TYPE_LENGTH (result_type) = 0; else { CHECK_TYPEDEF (element_type); - TYPE_LENGTH (result_type) = - TYPE_LENGTH (element_type) * (high_bound - low_bound + 1); + TYPE_LENGTH (result_type) = TYPE_LENGTH (element_type) + * (high_bound - low_bound + 1); } if (TYPE_LENGTH (result_type) == 0) @@ -1638,12 +1643,7 @@ check_typedef (struct type *type) constant values expected by the callers of this function. */ if (TYPE_DYNAMIC (type)) { - htab_t copied_types; - struct type *type_old = type; - - copied_types = create_copied_types_hash (NULL); - type = copy_type_recursive (type, copied_types); - htab_delete (copied_types); + type = copy_type_recursive (type, NULL); gdb_assert (TYPE_DYNAMIC (type) == 0); } @@ -3104,10 +3104,15 @@ copy_type_recursive_1 (struct objfile *objfile, if it did, the type might disappear unexpectedly. */ gdb_assert (TYPE_OBJFILE (type) == objfile); - pair.old = type; - slot = htab_find_slot (copied_types, &pair, INSERT); - if (*slot != NULL) - return ((struct type_pair *) *slot)->new; + if (copied_types) + { + pair.old = type; + slot = htab_find_slot (copied_types, &pair, INSERT); + if (*slot != NULL) + return ((struct type_pair *) *slot)->new; + } + else + slot = NULL; new_type = alloc_type (NULL); @@ -3115,10 +3120,13 @@ copy_type_recursive_1 (struct objfile *objfile, we encounter this type again during a recursive call below. Memory could be allocated from OBJFILE in the case we will be removing OBJFILE, this optimization is missed and xfree is called for it from COPIED_TYPES. */ - stored = xmalloc (sizeof (*stored)); - stored->old = type; - stored->new = new_type; - *slot = stored; + if (slot) + { + stored = xmalloc (sizeof (*stored)); + stored->old = type; + stored->new = new_type; + *slot = stored; + } /* Copy the common fields of types. For the main type, we simply copy the entire thing and then update specific fields as needed. */ @@ -3191,10 +3199,15 @@ copy_type_recursive_1 (struct objfile *objfile, TYPE_FIELD_ARTIFICIAL (new_type, i) = TYPE_FIELD_ARTIFICIAL (type, i); TYPE_FIELD_BITSIZE (new_type, i) = TYPE_FIELD_BITSIZE (type, i); - if (TYPE_FIELD_TYPE (type, i)) - TYPE_FIELD_TYPE (new_type, i) - = copy_type_recursive_1 (objfile, TYPE_FIELD_TYPE (type, i), - copied_types); + if (1 || copied_types) + { + if (TYPE_FIELD_TYPE (type, i)) + TYPE_FIELD_TYPE (new_type, i) + = copy_type_recursive_1 (objfile, TYPE_FIELD_TYPE (type, i), + copied_types); + } + else + TYPE_FIELD_TYPE (new_type, i) = TYPE_FIELD_TYPE (type, i); if (TYPE_FIELD_NAME (type, i)) TYPE_FIELD_NAME (new_type, i) = xstrdup (TYPE_FIELD_NAME (type, i)); @@ -3216,7 +3229,10 @@ copy_type_recursive_1 (struct objfile *objfile, case FIELD_LOC_KIND_DWARF_BLOCK: /* `struct dwarf2_locexpr_baton' is too bound to its objfile so it is expected to be made constant by CHECK_TYPEDEF. */ - if (TYPE_NOT_ALLOCATED (new_type) + if (0 && copied_types) + SET_FIELD_DWARF_BLOCK (TYPE_FIELD (new_type, i), + TYPE_FIELD_DWARF_BLOCK (type, i)); + else if (TYPE_NOT_ALLOCATED (new_type) || TYPE_NOT_ASSOCIATED (new_type)) SET_FIELD_DWARF_BLOCK (TYPE_FIELD (new_type, i), NULL); else @@ -3231,30 +3247,42 @@ copy_type_recursive_1 (struct objfile *objfile, } } - /* Convert TYPE_RANGE_HIGH_BOUND_IS_COUNT into a regular bound. */ - if (TYPE_CODE (type) == TYPE_CODE_RANGE - && TYPE_RANGE_HIGH_BOUND_IS_COUNT (type)) + if (copied_types) { - TYPE_RANGE_HIGH_BOUND_IS_COUNT (new_type) = 0; - TYPE_HIGH_BOUND (new_type) = TYPE_LOW_BOUND (type) - + TYPE_HIGH_BOUND (type) - 1; + /* Copy pointers to other types. */ + if (TYPE_TARGET_TYPE (type)) + TYPE_TARGET_TYPE (new_type) = + copy_type_recursive_1 (objfile, + TYPE_TARGET_TYPE (type), + copied_types); + if (TYPE_VPTR_BASETYPE (type)) + TYPE_VPTR_BASETYPE (new_type) = + copy_type_recursive_1 (objfile, + TYPE_VPTR_BASETYPE (type), + copied_types); + } + else + { + TYPE_TARGET_TYPE (new_type) = TYPE_TARGET_TYPE (type); + TYPE_VPTR_BASETYPE (new_type) = TYPE_VPTR_BASETYPE (type); } - /* Both FIELD_LOC_KIND_DWARF_BLOCK and TYPE_RANGE_HIGH_BOUND_IS_COUNT were - possibly converted. */ - TYPE_DYNAMIC (new_type) = 0; + if (copied_types == NULL) + { + /* Convert TYPE_RANGE_HIGH_BOUND_IS_COUNT into a regular bound. */ + if (TYPE_CODE (type) == TYPE_CODE_RANGE + && TYPE_RANGE_HIGH_BOUND_IS_COUNT (type)) + { + TYPE_RANGE_HIGH_BOUND_IS_COUNT (new_type) = 0; + TYPE_HIGH_BOUND (new_type) = TYPE_LOW_BOUND (type) + + TYPE_HIGH_BOUND (type) - 1; + } + + /* Both FIELD_LOC_KIND_DWARF_BLOCK and TYPE_RANGE_HIGH_BOUND_IS_COUNT were + possibly converted. */ + TYPE_DYNAMIC (new_type) = 0; + } - /* Copy pointers to other types. */ - if (TYPE_TARGET_TYPE (type)) - TYPE_TARGET_TYPE (new_type) = - copy_type_recursive_1 (objfile, - TYPE_TARGET_TYPE (type), - copied_types); - if (TYPE_VPTR_BASETYPE (type)) - TYPE_VPTR_BASETYPE (new_type) = - copy_type_recursive_1 (objfile, - TYPE_VPTR_BASETYPE (type), - copied_types); /* Maybe copy the type_specific bits. NOTE drow/2005-12-09: We do not copy the C++-specific bits like diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h index aca3f07..362d31c 100644 --- a/gdb/gdbtypes.h +++ b/gdb/gdbtypes.h @@ -945,10 +945,11 @@ extern void allocate_cplus_struct_type (struct type *); #define FIELD_TYPE(thisfld) ((thisfld).type) #define FIELD_NAME(thisfld) ((thisfld).name) #define FIELD_LOC_KIND(thisfld) ((thisfld).loc_kind) -#define FIELD_BITPOS(thisfld) ((thisfld).loc.bitpos) -#define FIELD_STATIC_PHYSNAME(thisfld) ((thisfld).loc.physname) -#define FIELD_STATIC_PHYSADDR(thisfld) ((thisfld).loc.physaddr) -#define FIELD_DWARF_BLOCK(thisfld) ((thisfld).loc.dwarf_block) +#include "gdb_assert.h" +#define FIELD_BITPOS(thisfld) (*({ gdb_assert (FIELD_LOC_KIND (thisfld) == FIELD_LOC_KIND_BITPOS); &(thisfld).loc.bitpos; })) +#define FIELD_STATIC_PHYSNAME(thisfld) (*({ gdb_assert (FIELD_LOC_KIND (thisfld) == FIELD_LOC_KIND_PHYSNAME); &(thisfld).loc.physname; })) +#define FIELD_STATIC_PHYSADDR(thisfld) (*({ gdb_assert (FIELD_LOC_KIND (thisfld) == FIELD_LOC_KIND_PHYSADDR); &(thisfld).loc.physaddr; })) +#define FIELD_DWARF_BLOCK(thisfld) (*({ gdb_assert (FIELD_LOC_KIND (thisfld) == FIELD_LOC_KIND_DWARF_BLOCK); &(thisfld).loc.dwarf_block; })) #define SET_FIELD_BITPOS(thisfld, bitpos) \ (FIELD_LOC_KIND (thisfld) = FIELD_LOC_KIND_BITPOS, \ FIELD_BITPOS (thisfld) = (bitpos)) diff --git a/gdb/p-typeprint.c b/gdb/p-typeprint.c index 5085fb4..8dd22c8 100644 --- a/gdb/p-typeprint.c +++ b/gdb/p-typeprint.c @@ -265,8 +265,7 @@ pascal_type_print_varspec_prefix (struct type *type, struct ui_file *stream, if (passed_a_ptr) fprintf_filtered (stream, "("); fprintf_filtered (stream, "array "); - if (TYPE_LENGTH (TYPE_TARGET_TYPE (type)) > 0 - && !TYPE_ARRAY_UPPER_BOUND_IS_UNDEFINED (type)) + if (!TYPE_ARRAY_UPPER_BOUND_IS_UNDEFINED (type)) fprintf_filtered (stream, "[%d..%d] ", TYPE_ARRAY_LOWER_BOUND_VALUE (type), TYPE_ARRAY_UPPER_BOUND_VALUE (type) diff --git a/gdb/p-valprint.c b/gdb/p-valprint.c index 30d0650..174b74d 100644 --- a/gdb/p-valprint.c +++ b/gdb/p-valprint.c @@ -71,6 +71,7 @@ pascal_val_print (struct type *type, const gdb_byte *valaddr, case TYPE_CODE_ARRAY: if (TYPE_LENGTH (type) > 0 && TYPE_LENGTH (TYPE_TARGET_TYPE (type)) > 0) { + case TYPE_CODE_STRING: elttype = check_typedef (TYPE_TARGET_TYPE (type)); eltlen = TYPE_LENGTH (elttype); len = TYPE_LENGTH (type) / eltlen; diff --git a/gdb/testsuite/gdb.arch/x86_64-pascal-string-array-foo.S b/gdb/testsuite/gdb.arch/x86_64-pascal-string-array-foo.S new file mode 100644 index 0000000..ef4ba2a --- /dev/null +++ b/gdb/testsuite/gdb.arch/x86_64-pascal-string-array-foo.S @@ -0,0 +1,447 @@ + .file "x86_64-pascal-string-array.c" + .section .debug_abbrev,"",@progbits +.Ldebug_abbrev0: + .section .debug_info,"",@progbits +.Ldebug_info0: + .section .debug_line,"",@progbits +.Ldebug_line0: + .text +.Ltext0: + .section .rodata +.LC0: + .string "alX" + .text +.globl foo + .type foo, @function +foo: +.LFB0: + .file 1 "x86_64-pascal-string-array.c" + # x86_64-pascal-string-array.c:22 + .loc 1 22 0 + .cfi_startproc + # basic block 2 + pushq %rbp + .cfi_def_cfa_offset 16 + movq %rsp, %rbp + .cfi_offset 6, -16 + .cfi_def_cfa_register 6 + pushq %rbx + movl %edi, -116(%rbp) + # x86_64-pascal-string-array.c:23 + .loc 1 23 0 + movw $22636, -32(%rbp) + movb $0, -30(%rbp) + # x86_64-pascal-string-array.c:24 + .loc 1 24 0 + movl .LC0(%rip), %eax + movl %eax, -48(%rbp) + # x86_64-pascal-string-array.c:25 + .loc 1 25 0 + movl $1483498338, -64(%rbp) + movb $0, -60(%rbp) + # x86_64-pascal-string-array.c:33 + .loc 1 33 0 + movl -116(%rbp), %eax + movslq %eax,%rcx + # x86_64-pascal-string-array.c:32 + .loc 1 32 0 + movl -116(%rbp), %eax + addl $1, %eax + # x86_64-pascal-string-array.c:33 + .loc 1 33 0 + movslq %eax,%rdx + movl -116(%rbp), %eax + addl $2, %eax + cltq + leaq -32(%rbp), %rbx + .cfi_offset 3, -24 + movq %rbx, -112(%rbp) + movq %rcx, -104(%rbp) + leaq -48(%rbp), %rcx + movq %rcx, -96(%rbp) + movq %rdx, -88(%rbp) + leaq -64(%rbp), %rdx + movq %rdx, -80(%rbp) + movq %rax, -72(%rbp) + # x86_64-pascal-string-array.c:36 + .loc 1 36 0 + popq %rbx + leave + ret + .cfi_endproc +.LFE0: + .size foo, .-foo +.Letext0: + .section .debug_loc,"",@progbits +.Ldebug_loc0: +.LLST0: + .quad .LFB0-.Ltext0 # Location list begin address (*.LLST0) + .quad .LFE0-.Ltext0 # Location list end address (*.LLST0) + .value 0x2 # Location expression size + .byte 0x76 # DW_OP_breg6 + .sleb128 16 + .quad 0x0 # Location list terminator begin (*.LLST0) + .quad 0x0 # Location list terminator end (*.LLST0) + .section .debug_info +.Lo0: + .long .Ldebuginfo_end-1f # Length of Compilation Unit Info +1: + .value 0x2 # DWARF version number + .long .Ldebug_abbrev0 # Offset Into Abbrev. Section + .byte 0x8 # Pointer Size (in bytes) + .uleb128 0x1 # (DIE (0xb) DW_TAG_compile_unit) + .long .LASF8 # DW_AT_producer: "GNU C 4.4.0 20090506 (Red Hat 4.4.0-4)" + .byte 0x9 # DW_AT_language = DW_LANG_Pascal83 + .long .LASF9 # DW_AT_name: "x86_64-pascal-string-array.c" + .long .LASF10 # DW_AT_comp_dir: "" + .quad .Ltext0 # DW_AT_low_pc + .quad .Letext0 # DW_AT_high_pc + .long .Ldebug_line0 # DW_AT_stmt_list + .uleb128 0x2 # (DIE (0x2d) DW_TAG_subprogram) + .byte 0x1 # DW_AT_external + .ascii "foo\0" # DW_AT_name + .byte 0x1 # DW_AT_decl_file (x86_64-pascal-string-array.c) + .byte 0x15 # DW_AT_decl_line + .byte 0x1 # DW_AT_prototyped + .quad .LFB0 # DW_AT_low_pc + .quad .LFE0 # DW_AT_high_pc + .long .LLST0 # DW_AT_frame_base + .uleb128 0x3 # (DIE (0x4e) DW_TAG_formal_parameter) + .long .LASF11 # DW_AT_name: "show_l" + .byte 0x1 # DW_AT_decl_file (x86_64-pascal-string-array.c) + .byte 0x15 # DW_AT_decl_line + .long .Ldie0xc1-.Lo0 # DW_AT_type + .byte 0x3 # DW_AT_location + .byte 0x91 # DW_OP_fbreg + .sleb128 -132 + .uleb128 0x4 # (DIE (0x5d) DW_TAG_variable) + .long .LASF0 # DW_AT_name: "string0" + .byte 0x1 # DW_AT_decl_file (x86_64-pascal-string-array.c) + .byte 0x17 # DW_AT_decl_line + .long .Ldie0xe2-.Lo0 # DW_AT_type + .byte 0x2 # DW_AT_location + .byte 0x91 # DW_OP_fbreg + .sleb128 -48 + .uleb128 0x4 # (DIE (0x6b) DW_TAG_variable) + .long .LASF1 # DW_AT_name: "string1" + .byte 0x1 # DW_AT_decl_file (x86_64-pascal-string-array.c) + .byte 0x18 # DW_AT_decl_line + .long .Ldie0xf7-.Lo0 # DW_AT_type + .byte 0x2 # DW_AT_location + .byte 0x91 # DW_OP_fbreg + .sleb128 -64 + .uleb128 0x4 # (DIE (0x79) DW_TAG_variable) + .long .LASF2 # DW_AT_name: "string2" + .byte 0x1 # DW_AT_decl_file (x86_64-pascal-string-array.c) + .byte 0x19 # DW_AT_decl_line + .long .Ldie0x10c-.Lo0 # DW_AT_type + .byte 0x3 # DW_AT_location + .byte 0x91 # DW_OP_fbreg + .sleb128 -80 +.Ldie0x88: + .uleb128 0x5 # (DIE (0x88) DW_TAG_string_type) + .long .LASF12 # DW_AT_name: "string_t" + .byte 0x8 # DW_AT_byte_size = sizeof (string_t.length) + .byte 2f-1f # DW_AT_string_length +1: .byte 0x97 # DW_OP_push_object_address + .byte 0x23 # DW_OP_plus_uconst + .uleb128 8 # offsetof (struct string_t, length) +2: + .byte 2f-1f # DW_AT_data_location +1: .byte 0x97 # DW_OP_push_object_address + .byte 0x06 # DW_OP_deref +2: + .byte 0x1 # DW_AT_decl_file (x86_64-pascal-string-array.c) + .byte 0x1b # DW_AT_decl_line + .uleb128 0x4 # (DIE (0xb1) DW_TAG_variable) + .long .LASF5 # DW_AT_name: "array" + .byte 0x1 # DW_AT_decl_file (x86_64-pascal-string-array.c) + .byte 0x1f # DW_AT_decl_line + .long .Ldie0x123-.Lo0 # DW_AT_type + .byte 0x3 # DW_AT_location + .byte 0x91 # DW_OP_fbreg + .sleb128 -128 + .byte 0x0 # end of children of DIE 0x2d +.Ldie0xc1: + .uleb128 0x7 # (DIE (0xc1) DW_TAG_base_type) + .byte 0x4 # DW_AT_byte_size + .byte 0x5 # DW_AT_encoding + .ascii "int\0" # DW_AT_name +.Ldie0xc8: + .uleb128 0x8 # (DIE (0xc8) DW_TAG_array_type) + .long .Ldie0xdb-.Lo0 # DW_AT_type + .uleb128 0x9 # (DIE (0xd1) DW_TAG_subrange_type) + .long .Ldie0xd8-.Lo0 # DW_AT_type + .byte 0x2 # DW_AT_upper_bound + .byte 0x0 # end of children of DIE 0xc8 +.Ldie0xd8: + .uleb128 0xa # (DIE (0xd8) DW_TAG_base_type) + .byte 0x8 # DW_AT_byte_size + .byte 0x7 # DW_AT_encoding +.Ldie0xdb: + .uleb128 0xb # (DIE (0xdb) DW_TAG_base_type) + .byte 0x1 # DW_AT_byte_size + .byte 0x6 # DW_AT_encoding + .long .LASF6 # DW_AT_name: "char" +.Ldie0xe2: + .uleb128 0xc # (DIE (0xe2) DW_TAG_const_type) + .long .Ldie0xc8-.Lo0 # DW_AT_type +.Ldie0xe7: + .uleb128 0x8 # (DIE (0xe7) DW_TAG_array_type) + .long .Ldie0xdb-.Lo0 # DW_AT_type + .uleb128 0x9 # (DIE (0xf0) DW_TAG_subrange_type) + .long .Ldie0xd8-.Lo0 # DW_AT_type + .byte 0x3 # DW_AT_upper_bound + .byte 0x0 # end of children of DIE 0xe7 +.Ldie0xf7: + .uleb128 0xc # (DIE (0xf7) DW_TAG_const_type) + .long .Ldie0xe7-.Lo0 # DW_AT_type +.Ldie0xfc: + .uleb128 0x8 # (DIE (0xfc) DW_TAG_array_type) + .long .Ldie0xdb-.Lo0 # DW_AT_type + .uleb128 0x9 # (DIE (0x105) DW_TAG_subrange_type) + .long .Ldie0xd8-.Lo0 # DW_AT_type + .byte 0x4 # DW_AT_upper_bound + .byte 0x0 # end of children of DIE 0xfc +.Ldie0x10c: + .uleb128 0xc # (DIE (0x10c) DW_TAG_const_type) + .long .Ldie0xfc-.Lo0 # DW_AT_type + .uleb128 0xd # (DIE (0x111) DW_TAG_pointer_type) + .byte 0x8 # DW_AT_byte_size + .long .Ldie0x117-.Lo0 # DW_AT_type +.Ldie0x117: + .uleb128 0xc # (DIE (0x117) DW_TAG_const_type) + .long .Ldie0xdb-.Lo0 # DW_AT_type + .uleb128 0xb # (DIE (0x11c) DW_TAG_base_type) + .byte 0x8 # DW_AT_byte_size + .byte 0x7 # DW_AT_encoding + .long .LASF7 # DW_AT_name: "long unsigned int" +.Ldie0x123: + .uleb128 0xe # (DIE (0x123) DW_TAG_array_type) + .long .Ldie0x88-.Lo0 # DW_AT_type + .uleb128 0xf # (DIE (0x128) DW_TAG_subrange_type) + .long .Ldie0xd8-.Lo0 # DW_AT_type + .byte 0x2 # DW_AT_upper_bound + .byte 0x10 # DW_AT_byte_stride + .byte 0x0 # end of children of DIE 0x123 + .byte 0x0 # end of children of DIE 0xb +.Ldebuginfo_end: + .section .debug_abbrev + .uleb128 0x1 # (abbrev code) + .uleb128 0x11 # (TAG: DW_TAG_compile_unit) + .byte 0x1 # DW_children_yes + .uleb128 0x25 # (DW_AT_producer) + .uleb128 0xe # (DW_FORM_strp) + .uleb128 0x13 # (DW_AT_language) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x3 # (DW_AT_name) + .uleb128 0xe # (DW_FORM_strp) + .uleb128 0x1b # (DW_AT_comp_dir) + .uleb128 0xe # (DW_FORM_strp) + .uleb128 0x11 # (DW_AT_low_pc) + .uleb128 0x1 # (DW_FORM_addr) + .uleb128 0x12 # (DW_AT_high_pc) + .uleb128 0x1 # (DW_FORM_addr) + .uleb128 0x10 # (DW_AT_stmt_list) + .uleb128 0x6 # (DW_FORM_data4) + .byte 0x0 + .byte 0x0 + .uleb128 0x2 # (abbrev code) + .uleb128 0x2e # (TAG: DW_TAG_subprogram) + .byte 0x1 # DW_children_yes + .uleb128 0x3f # (DW_AT_external) + .uleb128 0xc # (DW_FORM_flag) + .uleb128 0x3 # (DW_AT_name) + .uleb128 0x8 # (DW_FORM_string) + .uleb128 0x3a # (DW_AT_decl_file) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x3b # (DW_AT_decl_line) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x27 # (DW_AT_prototyped) + .uleb128 0xc # (DW_FORM_flag) + .uleb128 0x11 # (DW_AT_low_pc) + .uleb128 0x1 # (DW_FORM_addr) + .uleb128 0x12 # (DW_AT_high_pc) + .uleb128 0x1 # (DW_FORM_addr) + .uleb128 0x40 # (DW_AT_frame_base) + .uleb128 0x6 # (DW_FORM_data4) + .byte 0x0 + .byte 0x0 + .uleb128 0x3 # (abbrev code) + .uleb128 0x5 # (TAG: DW_TAG_formal_parameter) + .byte 0x0 # DW_children_no + .uleb128 0x3 # (DW_AT_name) + .uleb128 0xe # (DW_FORM_strp) + .uleb128 0x3a # (DW_AT_decl_file) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x3b # (DW_AT_decl_line) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x49 # (DW_AT_type) + .uleb128 0x13 # (DW_FORM_ref4) + .uleb128 0x2 # (DW_AT_location) + .uleb128 0xa # (DW_FORM_block1) + .byte 0x0 + .byte 0x0 + .uleb128 0x4 # (abbrev code) + .uleb128 0x34 # (TAG: DW_TAG_variable) + .byte 0x0 # DW_children_no + .uleb128 0x3 # (DW_AT_name) + .uleb128 0xe # (DW_FORM_strp) + .uleb128 0x3a # (DW_AT_decl_file) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x3b # (DW_AT_decl_line) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x49 # (DW_AT_type) + .uleb128 0x13 # (DW_FORM_ref4) + .uleb128 0x2 # (DW_AT_location) + .uleb128 0xa # (DW_FORM_block1) + .byte 0x0 + .byte 0x0 + .uleb128 0x5 # (abbrev code) + .uleb128 0x12 # (TAG: DW_TAG_string_type) + .byte 0x0 # DW_children_no + .uleb128 0x3 # (DW_AT_name) + .uleb128 0xe # (DW_FORM_strp) + .uleb128 0xb # (DW_AT_byte_size) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x19 # (DW_AT_string_length) + .uleb128 0xa # (DW_FORM_block1) + .uleb128 0x50 # (DW_AT_data_location) + .uleb128 0xa # (DW_FORM_block1) + .uleb128 0x3a # (DW_AT_decl_file) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x3b # (DW_AT_decl_line) + .uleb128 0xb # (DW_FORM_data1) + .byte 0x0 + .byte 0x0 + .uleb128 0x7 # (abbrev code) + .uleb128 0x24 # (TAG: DW_TAG_base_type) + .byte 0x0 # DW_children_no + .uleb128 0xb # (DW_AT_byte_size) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x3e # (DW_AT_encoding) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x3 # (DW_AT_name) + .uleb128 0x8 # (DW_FORM_string) + .byte 0x0 + .byte 0x0 + .uleb128 0x8 # (abbrev code) + .uleb128 0x1 # (TAG: DW_TAG_array_type) + .byte 0x1 # DW_children_yes + .uleb128 0x49 # (DW_AT_type) + .uleb128 0x13 # (DW_FORM_ref4) + .byte 0x0 + .byte 0x0 + .uleb128 0x9 # (abbrev code) + .uleb128 0x21 # (TAG: DW_TAG_subrange_type) + .byte 0x0 # DW_children_no + .uleb128 0x49 # (DW_AT_type) + .uleb128 0x13 # (DW_FORM_ref4) + .uleb128 0x2f # (DW_AT_upper_bound) + .uleb128 0xb # (DW_FORM_data1) + .byte 0x0 + .byte 0x0 + .uleb128 0xa # (abbrev code) + .uleb128 0x24 # (TAG: DW_TAG_base_type) + .byte 0x0 # DW_children_no + .uleb128 0xb # (DW_AT_byte_size) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x3e # (DW_AT_encoding) + .uleb128 0xb # (DW_FORM_data1) + .byte 0x0 + .byte 0x0 + .uleb128 0xb # (abbrev code) + .uleb128 0x24 # (TAG: DW_TAG_base_type) + .byte 0x0 # DW_children_no + .uleb128 0xb # (DW_AT_byte_size) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x3e # (DW_AT_encoding) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x3 # (DW_AT_name) + .uleb128 0xe # (DW_FORM_strp) + .byte 0x0 + .byte 0x0 + .uleb128 0xc # (abbrev code) + .uleb128 0x26 # (TAG: DW_TAG_const_type) + .byte 0x0 # DW_children_no + .uleb128 0x49 # (DW_AT_type) + .uleb128 0x13 # (DW_FORM_ref4) + .byte 0x0 + .byte 0x0 + .uleb128 0xd # (abbrev code) + .uleb128 0xf # (TAG: DW_TAG_pointer_type) + .byte 0x0 # DW_children_no + .uleb128 0xb # (DW_AT_byte_size) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x49 # (DW_AT_type) + .uleb128 0x13 # (DW_FORM_ref4) + .byte 0x0 + .byte 0x0 + .uleb128 0xe # (abbrev code) + .uleb128 0x1 # (TAG: DW_TAG_array_type) + .byte 0x1 # DW_children_yes + .uleb128 0x49 # (DW_AT_type) + .uleb128 0x13 # (DW_FORM_ref4) + .byte 0x0 + .byte 0x0 + .uleb128 0xf # (abbrev code) + .uleb128 0x21 # (TAG: DW_TAG_subrange_type) + .byte 0x0 # DW_children_no + .uleb128 0x49 # (DW_AT_type) + .uleb128 0x13 # (DW_FORM_ref4) + .uleb128 0x2f # (DW_AT_upper_bound) + .uleb128 0xb # (DW_FORM_data1) + .uleb128 0x51 # (DW_AT_byte_stride) + .uleb128 0xb # (DW_FORM_data1) + .byte 0x0 + .byte 0x0 + .byte 0x0 + .section .debug_pubnames,"",@progbits + .long 0x16 # Length of Public Names Info + .value 0x2 # DWARF Version + .long .Ldebug_info0 # Offset of Compilation Unit Info + .long 0x130 # Compilation Unit Length + .long 0x2d # DIE offset + .ascii "foo\0" # external name + .long 0x0 + .section .debug_aranges,"",@progbits + .long 0x2c # Length of Address Ranges Info + .value 0x2 # DWARF Version + .long .Ldebug_info0 # Offset of Compilation Unit Info + .byte 0x8 # Size of Address + .byte 0x0 # Size of Segment Descriptor + .value 0x0 # Pad to 16 byte boundary + .value 0x0 + .quad .Ltext0 # Address + .quad .Letext0-.Ltext0 # Length + .quad 0x0 + .quad 0x0 + .section .debug_str,"MS",@progbits,1 +.LASF12: + .string "string_t" +.LASF0: + .string "string0" +.LASF5: + .string "array" +.LASF1: + .string "string1" +.LASF4: + .string "length" +.LASF10: + .string "" +.LASF7: + .string "long unsigned int" +.LASF6: + .string "char" +.LASF3: + .string "string" +.LASF9: + .string "x86_64-pascal-string-array.c" +.LASF8: + .string "GNU C 4.4.0 20090506 (Red Hat 4.4.0-4)" +.LASF11: + .string "show_l" +.LASF2: + .string "string2" + .ident "GCC: (GNU) 4.4.0 20090506 (Red Hat 4.4.0-4)" + .section .note.GNU-stack,"",@progbits diff --git a/gdb/testsuite/gdb.arch/x86_64-pascal-string-array.c b/gdb/testsuite/gdb.arch/x86_64-pascal-string-array.c new file mode 100644 index 0000000..fc2c541 --- /dev/null +++ b/gdb/testsuite/gdb.arch/x86_64-pascal-string-array.c @@ -0,0 +1,48 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2009 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#if 0 + +void +foo (int show_l) +{ + const char string0[] = "lX"; + const char string1[] = "alX"; + const char string2[] = "bclX"; + struct string_t + { + const char *string; + unsigned long length; + } + array[3] = {{string0, 0 + show_l}, + {string1, 1 + show_l}, + {string2, 2 + show_l}}; + + show_l = show_l; /* break-here */ +} + +#else + +int +main (void) +{ + foo (0); + foo (1); + return 0; +} + +#endif diff --git a/gdb/testsuite/gdb.arch/x86_64-pascal-string-array.exp b/gdb/testsuite/gdb.arch/x86_64-pascal-string-array.exp new file mode 100644 index 0000000..94e4547 --- /dev/null +++ b/gdb/testsuite/gdb.arch/x86_64-pascal-string-array.exp @@ -0,0 +1,64 @@ +# Copyright 2009 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +# Test DW_AT_data_location accessed through DW_TAG_typedef intermediate. + +if ![istarget "x86_64-*-*"] then { + verbose "Skipping over gdb.arch/x86_64-pascal-string-array.exp test made only for x86_64." + return +} + +set test x86_64-pascal-string-array +set srcfile ${test}.c + +# Disable {debug} options as the .c debug_line would conflict with -foo.S. +if { [prepare_for_testing ${test}.exp ${test} [list ${test}-foo.S ${test}.c] {}] } { + return -1 +} + +if ![runto_main] { + untested ${test}.exp + return -1 +} + +gdb_breakpoint [gdb_get_line_number "break-here"] +gdb_continue_to_breakpoint "break-here" + +gdb_test "whatis array" "type = array \\\[0\\.\\.2\\\] of string_t" "first: whatis array" +gdb_test "ptype array" "type = array \\\[0\\.\\.2\\\] of string_t" "first: ptype array" + +set test "first: p array\[0\]" +gdb_test_multiple "p array\[0\]" $test { + -re " = 0x\[0-9a-f\]+ 'lX'\r\n$gdb_prompt $" { + # pascal_val_print currently considers TYPE_LENGTH == 0 as unspecified. +### setup_kfail *-*-* gdb/9999 + fail $test + } + -re " = ''\r\n$gdb_prompt $" { + pass $test + } +} +gdb_test "p array\[1\]" " = 'a'" "first: p array\[1\]" +gdb_test "p array\[2\]" " = 'bc'" "first: p array\[2\]" + +gdb_continue_to_breakpoint "break-here" + +gdb_test "whatis array" "type = array \\\[0\\.\\.2\\\] of string_t" "second: whatis array" +gdb_test "ptype array" "type = array \\\[0\\.\\.2\\\] of string_t" "second: ptype array" + +gdb_test "p array\[0\]" " = 'l'" "second: p array\[0\]" +gdb_test "p array\[1\]" " = 'al'" "second: p array\[1\]" +gdb_test "p array\[2\]" " = 'bcl'" "second: p array\[2\]" + diff --git a/gdb/valarith.c b/gdb/valarith.c index 8a635b6..ad4489c 100644 --- a/gdb/valarith.c +++ b/gdb/valarith.c @@ -31,6 +31,7 @@ #include "dfp.h" #include #include "infcall.h" +#include "dwarf2loc.h" /* Define whether or not the C operator '/' truncates towards zero for differently signed operands (truncation direction is undefined in C). */ @@ -178,11 +179,12 @@ value_subscript (struct value *array, struct value *idx) LONGEST lowerbound, upperbound; get_discrete_bounds (range_type, &lowerbound, &upperbound); - if (VALUE_LVAL (array) != lval_memory) + if (VALUE_LVAL (array) != lval_memory + || TYPE_BYTE_STRIDE (range_type) > 0) { if (index >= lowerbound && index <= upperbound) { - CORE_ADDR element_size = TYPE_LENGTH (TYPE_TARGET_TYPE (tarray)); + CORE_ADDR element_size = TYPE_ARRAY_BYTE_STRIDE_VALUE (tarray); CORE_ADDR offset = (index - lowerbound) * element_size; return value_subscripted_rvalue (array, offset); @@ -232,8 +234,26 @@ struct value * value_subscripted_rvalue (struct value *array, CORE_ADDR offset) { struct type *array_type = check_typedef (value_type (array)); - struct type *elt_type = check_typedef (TYPE_TARGET_TYPE (array_type)); + struct type *elt_type; struct value *v; + struct cleanup *back_to; + CORE_ADDR elt_addr; + + back_to = make_cleanup (null_cleanup, 0); + + /* Find the element object address - derived from the array _data_ address + shifted by OFFSET. */ + elt_addr = value_raw_address (array); + object_address_get_data (value_type (array), &elt_addr); + elt_addr += offset; + + /* And get the appropriate TYPE for the specific element of the array. + Different elements of the array may get different (such as by their string + length) types). */ + object_address_set (elt_addr); + elt_type = check_typedef (TYPE_TARGET_TYPE (array_type)); + + do_cleanups (back_to); /* Do not check TYPE_LENGTH (array_type) as we may have been given the innermost dimension of a multi-dimensional Fortran array where its length @@ -252,7 +272,7 @@ value_subscripted_rvalue (struct value *array, CORE_ADDR offset) set_value_component_location (v, array); VALUE_REGNUM (v) = VALUE_REGNUM (array); VALUE_FRAME_ID (v) = VALUE_FRAME_ID (array); - set_value_offset (v, value_offset (array) + offset); + set_value_address (v, elt_addr); return v; } diff --git a/gdb/valops.c b/gdb/valops.c index acd67f0..befc6be 100644 --- a/gdb/valops.c +++ b/gdb/valops.c @@ -318,6 +318,7 @@ value_cast (struct type *type, struct value *arg2) enum type_code code2; int scalar; struct type *type2; + struct cleanup *back_to; int convert_to_boolean = 0; @@ -338,17 +339,26 @@ value_cast (struct type *type, struct value *arg2) return value_ref (val); } + back_to = make_cleanup (null_cleanup, 0); + object_address_set (value_raw_address (arg2)); + code2 = TYPE_CODE (check_typedef (value_type (arg2))); + arg2 = coerce_ref (arg2); if (code2 == TYPE_CODE_REF) - /* We deref the value and then do the cast. */ - return value_cast (type, coerce_ref (arg2)); + { + do_cleanups (back_to); + + /* We deref the value and then do the cast. */ + return value_cast (type, arg2); + } CHECK_TYPEDEF (type); code1 = TYPE_CODE (type); - arg2 = coerce_ref (arg2); type2 = check_typedef (value_type (arg2)); + do_cleanups (back_to); + /* You can't cast to a reference type. See value_cast_pointers instead. */ gdb_assert (code1 != TYPE_CODE_REF);