From patchwork Thu Jan 12 19:24:27 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andreas Arnez X-Patchwork-Id: 18885 Received: (qmail 72902 invoked by alias); 12 Jan 2017 19:24:48 -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 72886 invoked by uid 89); 12 Jan 2017 19:24:48 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.5 required=5.0 tests=AWL, BAYES_00, KAM_LAZY_DOMAIN_SECURITY, RCVD_IN_DNSWL_LOW autolearn=no version=3.3.2 spammy=*frame, Struct, base_type, H*o:Research X-HELO: mx0a-001b2d01.pphosted.com Received: from mx0a-001b2d01.pphosted.com (HELO mx0a-001b2d01.pphosted.com) (148.163.156.1) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Thu, 12 Jan 2017 19:24:38 +0000 Received: from pps.filterd (m0098410.ppops.net [127.0.0.1]) by mx0a-001b2d01.pphosted.com (8.16.0.17/8.16.0.17) with SMTP id v0CJJh3H026537 for ; Thu, 12 Jan 2017 14:24:36 -0500 Received: from e06smtp07.uk.ibm.com (e06smtp07.uk.ibm.com [195.75.94.103]) by mx0a-001b2d01.pphosted.com with ESMTP id 27xc949mac-1 (version=TLSv1.2 cipher=AES256-SHA bits=256 verify=NOT) for ; Thu, 12 Jan 2017 14:24:36 -0500 Received: from localhost by e06smtp07.uk.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Thu, 12 Jan 2017 19:24:34 -0000 Received: from d06dlp01.portsmouth.uk.ibm.com (9.149.20.13) by e06smtp07.uk.ibm.com (192.168.101.137) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Thu, 12 Jan 2017 19:24:32 -0000 Received: from b06cxnps4074.portsmouth.uk.ibm.com (d06relay11.portsmouth.uk.ibm.com [9.149.109.196]) by d06dlp01.portsmouth.uk.ibm.com (Postfix) with ESMTP id CD42417D8042; Thu, 12 Jan 2017 19:27:23 +0000 (GMT) Received: from d06av23.portsmouth.uk.ibm.com (d06av23.portsmouth.uk.ibm.com [9.149.105.59]) by b06cxnps4074.portsmouth.uk.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id v0CJOWHs4915622; Thu, 12 Jan 2017 19:24:32 GMT Received: from d06av23.portsmouth.uk.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 3691BA404D; Thu, 12 Jan 2017 18:22:29 +0000 (GMT) Received: from d06av23.portsmouth.uk.ibm.com (unknown [127.0.0.1]) by IMSVA (Postfix) with ESMTP id 02DB4A4040; Thu, 12 Jan 2017 18:22:29 +0000 (GMT) Received: from oc1027705133.ibm.com (unknown [9.152.212.222]) by d06av23.portsmouth.uk.ibm.com (Postfix) with ESMTPS; Thu, 12 Jan 2017 18:22:28 +0000 (GMT) From: Andreas Arnez To: gdb-patches@sourceware.org Cc: Jan Kratochvil Subject: [PATCH] Big-endian targets: don't ignore offset into DW_OP_implicit_value Date: Thu, 12 Jan 2017 20:24:27 +0100 User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/25.1 (gnu/linux) MIME-Version: 1.0 X-TM-AS-GCONF: 00 X-Content-Scanned: Fidelis XPS MAILER x-cbid: 17011219-0028-0000-0000-000002919411 X-IBM-AV-DETECTION: SAVI=unused REMOTE=unused XFE=unused x-cbparentid: 17011219-0029-0000-0000-000021FE8BB8 Message-Id: X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:, , definitions=2017-01-12_14:, , signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 spamscore=0 suspectscore=3 malwarescore=0 phishscore=0 adultscore=0 bulkscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1612050000 definitions=main-1701120255 X-IsSubscribed: yes When a variable's location is expressed as DW_OP_implicit_value, but the given value is longer than needed, which bytes should be used? GDB's current logic was introduced with a patch from 2011 and uses the "least significant" bytes: https://sourceware.org/ml/gdb-patches/2011-08/msg00123.html Now consider a sub-value from such a location at a given offset, accessed through DW_OP_implicit_pointer. Which bytes should be used for that? The patch above *always* uses the last bytes on big-endian targets, ignoring the offset. E.g., given the code snippet const char foo[] = "Hello, world!"; const char *a = &foo[0]; const char *b = &foo[7]; assume that `foo' is described as DW_OP_implicit_value and `a' and `b' each as DW_OP_implicit_pointer into that value. Then with current GDB `*a' and `*b' yield the same result -- the string's zero terminator. This patch basically reverts the portion of the patch above that deals with DW_OP_implicit_value. This fixes the offset handling and also goes back to dropping the last instead of the first bytes on big-endian targets if the implicit value is longer than needed. The latter aspect of the change probably doesn't matter for actual programs, but simplifies the logic. The patch also cleans up the original code a bit and adds appropriate test cases. gdb/testsuite/ChangeLog: * gdb.dwarf2/dw2-op-stack-value.exp: Adjust expected result of taking a 2-byte value out of a 4-byte DWARF implicit value on big-endian targets. * gdb.dwarf2/nonvar-access.exp: Add more comments to existing logic. Add test cases for DW_OP_implicit. * lib/dwarf.exp (_location): Add handling for DW_OP_implicit_value. gdb/ChangeLog: * dwarf2loc.c (dwarf2_evaluate_loc_desc_full): For DWARF_VALUE_LITERAL, no longer ignore the offset on big-endian targets. And if the implicit value is longer than needed, extract the first bytes instead of the "least significant" ones. --- gdb/dwarf2loc.c | 19 +----- gdb/testsuite/gdb.dwarf2/dw2-op-stack-value.exp | 2 +- gdb/testsuite/gdb.dwarf2/nonvar-access.exp | 78 ++++++++++++++++++++++++- gdb/testsuite/lib/dwarf.exp | 19 ++++++ 4 files changed, 99 insertions(+), 19 deletions(-) diff --git a/gdb/dwarf2loc.c b/gdb/dwarf2loc.c index 7fca76b..a592b66 100644 --- a/gdb/dwarf2loc.c +++ b/gdb/dwarf2loc.c @@ -2442,28 +2442,15 @@ dwarf2_evaluate_loc_desc_full (struct type *type, struct frame_info *frame, case DWARF_VALUE_LITERAL: { bfd_byte *contents; - const bfd_byte *ldata; - size_t n = ctx.len; + size_t n = TYPE_LENGTH (type); - if (byte_offset + TYPE_LENGTH (type) > n) + if (byte_offset + n > ctx.len) invalid_synthetic_pointer (); free_values.free_to_mark (); retval = allocate_value (type); contents = value_contents_raw (retval); - - ldata = ctx.data + byte_offset; - n -= byte_offset; - - if (n > TYPE_LENGTH (type)) - { - struct gdbarch *objfile_gdbarch = get_objfile_arch (objfile); - - if (gdbarch_byte_order (objfile_gdbarch) == BFD_ENDIAN_BIG) - ldata += n - TYPE_LENGTH (type); - n = TYPE_LENGTH (type); - } - memcpy (contents, ldata, n); + memcpy (contents, ctx.data + byte_offset, n); } break; diff --git a/gdb/testsuite/gdb.dwarf2/dw2-op-stack-value.exp b/gdb/testsuite/gdb.dwarf2/dw2-op-stack-value.exp index c28dcca..808f983 100644 --- a/gdb/testsuite/gdb.dwarf2/dw2-op-stack-value.exp +++ b/gdb/testsuite/gdb.dwarf2/dw2-op-stack-value.exp @@ -45,7 +45,7 @@ gdb_test_multiple $test $test { -re ":\[ \t\]*0xaa551234\r\n$gdb_prompt $" { # big endian pass $test - gdb_test "p/x implicit4to2" " = 0x3344" + gdb_test "p/x implicit4to2" " = 0x1122" gdb_test "p/x implicit4to4" " = 0x11223344" } -re ":\[ \t\]*0x\[0-9a-f\]{8}\r\n$gdb_prompt $" { diff --git a/gdb/testsuite/gdb.dwarf2/nonvar-access.exp b/gdb/testsuite/gdb.dwarf2/nonvar-access.exp index 506ff9e..f47df70 100644 --- a/gdb/testsuite/gdb.dwarf2/nonvar-access.exp +++ b/gdb/testsuite/gdb.dwarf2/nonvar-access.exp @@ -31,14 +31,23 @@ Dwarf::assemble $asm_file { compile_unit { {DW_AT_name main.c} } { - declare_labels int_type_label short_type_label - declare_labels struct_s_label struct_t_label + declare_labels int_type_label char_type_label \ + struct_s_label struct_t_label array_a9_label \ + char_ptr_label implicit_a_label int_type_label: base_type { {name "int"} {encoding @DW_ATE_signed} {byte_size 4 DW_FORM_sdata} } + char_type_label: base_type { + {name "char"} + {encoding @DW_ATE_unsigned} + {byte_size 1 DW_FORM_sdata} + } + char_ptr_label: pointer_type { + {type :$char_type_label} + } struct_s_label: structure_type { {name s} @@ -76,20 +85,32 @@ Dwarf::assemble $asm_file { } } + array_a9_label: array_type { + {type :$char_type_label} + } { + subrange_type { + {type :$int_type_label} + {upper_bound 8 DW_FORM_udata} + } + } + DW_TAG_subprogram { {name main} {DW_AT_external 1 flag} {low_pc [gdb_target_symbol main] DW_FORM_addr} {high_pc [gdb_target_symbol main]+0x10000 DW_FORM_addr} } { + # Simple variable without location. DW_TAG_variable { {name undef_int} {type :$int_type_label} } + # Struct variable without location. DW_TAG_variable { {name undef_s} {type :$struct_s_label} } + # Composite location: byte-aligned pieces. DW_TAG_variable { {name def_s} {type :$struct_s_label} @@ -102,6 +123,7 @@ Dwarf::assemble $asm_file { bit_piece 24 0 } SPECIAL_expr} } + # Composite location: non-byte-aligned pieces. DW_TAG_variable { {name def_t} {type :$struct_t_label} @@ -114,6 +136,32 @@ Dwarf::assemble $asm_file { bit_piece 23 0 } SPECIAL_expr} } + # Implicit location: immediate value. + DW_TAG_variable { + {name def_implicit_s} + {type :$struct_s_label} + {location { + implicit_value 0x12 0x34 0x56 0x78 + } SPECIAL_expr} + } + # Implicit location: immediate value for whole array, with + # excess bytes. + implicit_a_label: DW_TAG_variable { + {name def_implicit_a} + {type :$array_a9_label} + {location { + implicit_value 0x01 0x12 0x23 0x34 0x45 \ + 0x56 0x67 0x78 0x89 0x9a 0xab + } SPECIAL_expr} + } + # Implicit pointer into immediate value. + DW_TAG_variable { + {name implicit_a_ptr} + {type :$char_ptr_label} + {location { + GNU_implicit_pointer $implicit_a_label 5 + } SPECIAL_expr} + } } } } @@ -128,7 +176,33 @@ if ![runto_main] { return -1 } +# Determine endianness. +set endian "little" +gdb_test_multiple "show endian" "determine endianness" { + -re ".* (big|little) endian.*$gdb_prompt $" { + set endian $expect_out(1,string) + pass "endianness: $endian" + } +} + +# Byte-aligned objects with simple location descriptions. +switch $endian { big {set val 0x345678} little {set val 0x785634} } +gdb_test "print/x def_implicit_s" " = \\{a = 0x12, b = $val\\}" +gdb_test "print/x def_implicit_s.b" " = $val" +gdb_test "print/x def_implicit_a" \ + " = \\{0x1, 0x12, 0x23, 0x34, 0x45, 0x56, 0x67, 0x78, 0x89\\}" +gdb_test "print/x def_implicit_a\[5\]" " = 0x56" +gdb_test "print/x *(char (*)\[5\]) implicit_a_ptr" \ + " = \\{0x56, 0x67, 0x78, 0x89, 0x9a\\}" + +# Byte-aligned fields, pieced together from DWARF stack values. gdb_test "print def_s" " = \\{a = 0, b = -1\\}" + +# Non-byte-aligned fields, pieced together from DWARF stack values. gdb_test "print def_t" " = \\{a = 0, b = -1\\}" + +# Simple variable without location. gdb_test "print undef_int" " = " + +# Member of a structure without location. gdb_test "print undef_s.a" " = " diff --git a/gdb/testsuite/lib/dwarf.exp b/gdb/testsuite/lib/dwarf.exp index 9f5fa6c..6bd563a 100644 --- a/gdb/testsuite/lib/dwarf.exp +++ b/gdb/testsuite/lib/dwarf.exp @@ -906,6 +906,25 @@ namespace eval Dwarf { _op .2byte [lindex $line 1] } + DW_OP_implicit_value { + set l1 [new_label "value_start"] + set l2 [new_label "value_end"] + _op .uleb128 "$l2 - $l1" + define_label $l1 + foreach value [lrange $line 1 end] { + switch -regexp -- $value { + {^0x[[:xdigit:]]{2}$} {_op .byte $value} + {^0x[[:xdigit:]]{4}$} {_op .2byte $value} + {^0x[[:xdigit:]]{8}$} {_op .4byte $value} + {^0x[[:xdigit:]]{16}$} {_op .8byte $value} + default { + error "bad value '$value' in DW_OP_implicit_value" + } + } + } + define_label $l2 + } + DW_OP_GNU_implicit_pointer { if {[llength $line] != 3} { error "usage: DW_OP_GNU_implicit_pointer LABEL OFFSET"