From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 22694 invoked by alias); 13 Jul 2011 16:05:00 -0000 Received: (qmail 22686 invoked by uid 22791); 13 Jul 2011 16:04:58 -0000 X-SWARE-Spam-Status: No, hits=-5.6 required=5.0 tests=AWL,BAYES_00,KAM_STOCKGEN,RCVD_IN_DNSWL_HI,SPF_HELO_PASS,TW_DL,T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Wed, 13 Jul 2011 16:04:40 +0000 Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id p6DG4e32004290 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Wed, 13 Jul 2011 12:04:40 -0400 Received: from host1.jankratochvil.net ([10.3.113.13]) by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id p6DG4ckN006699 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) for ; Wed, 13 Jul 2011 12:04:39 -0400 Received: from host1.jankratochvil.net (localhost [127.0.0.1]) by host1.jankratochvil.net (8.14.4/8.14.4) with ESMTP id p6DG4a0T019662 for ; Wed, 13 Jul 2011 18:04:36 +0200 Received: (from jkratoch@localhost) by host1.jankratochvil.net (8.14.4/8.14.4/Submit) id p6DG4Z7b019657 for gdb-patches@sourceware.org; Wed, 13 Jul 2011 18:04:35 +0200 Date: Wed, 13 Jul 2011 17:03:00 -0000 From: Jan Kratochvil To: gdb-patches@sourceware.org Subject: [patch] Fix crash on empty DWARF expressions NULL DATA vs. zero SIZE Message-ID: <20110713160435.GA19359@host1.jankratochvil.net> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.5.21 (2010-09-15) X-IsSubscribed: yes Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2011-07/txt/msg00349.txt.bz2 Hi, GDB could crash as shown in the testcase. #1 0x0000000000750274 in dwarf_expr_eval (ctx=0x4175ce0, addr=0x0, len=4796440) at dwarf2expr.c:365 ^^^ Indication of empty () or otherwise invalid DWARF expressions some code expects to be NULL address, some code expects it to be zero size and another code checks for either NULL address or zero size. And some code creates them just with zero size (and non-NULL address), other code creates them with NULL address and undefined (=non-zero) size; some code creates them with both NULL address and zero size. I found safer indicator to be zero size, therefore unified to code on this indicator. Removed address clearing as redundant and confusing now. No regressions on {x86_64,x86_64-m32,i686}-fedora15-linux-gnu. Thanks, Jan gdb/ 2011-07-13 Jan Kratochvil Fix empty DWARF expressions DATA vs. SIZE conditionals. * dwarf2loc.c (dwarf2_find_location_expression): Clear *LOCEXPR_LENGTH. (dwarf_expr_frame_base_1): Indicate unavailability via zero *LENGTH. (locexpr_tracepoint_var_ref): Check only zero SIZE, not zero DATA. (loclist_read_variable, loclist_tracepoint_var_ref): Do not check for zero DATA. * dwarf2loc.h (struct dwarf2_locexpr_baton): Comment DATA vs. SIZE validity. * dwarf2read.c (struct dwarf_block): Comment DATA validity. (dwarf2_fetch_die_location_block, dwarf2_symbol_mark_computed): Do not clear DATA on zero SIZE. gdb/testsuite/ 2011-07-13 Jan Kratochvil Fix empty DWARF expressions DATA vs. SIZE conditionals. * gdb.dwarf2/dw2-op-call.S (arraycallnoloc, arraynoloc): New DIEs. (loclist): New. (4): New abbrev. * gdb.dwarf2/dw2-op-call.exp: Remove variable srcfile and executable. Use prepare_for_testing, remove clean_restart. (p arraynoloc, p arraycallnoloc): New tests. --- a/gdb/dwarf2loc.c +++ b/gdb/dwarf2loc.c @@ -109,7 +109,10 @@ dwarf2_find_location_expression (struct dwarf2_loclist_baton *baton, /* An end-of-list entry. */ if (low == 0 && high == 0) - return NULL; + { + *locexpr_length = 0; + return NULL; + } /* Otherwise, a location expression entry. */ low += base_address; @@ -194,7 +197,7 @@ dwarf_expr_frame_base_1 (struct symbol *framefunc, CORE_ADDR pc, const gdb_byte **start, size_t *length) { if (SYMBOL_LOCATION_BATON (framefunc) == NULL) - *start = NULL; + *length = 0; else if (SYMBOL_COMPUTED_OPS (framefunc) == &dwarf2_loclist_funcs) { struct dwarf2_loclist_baton *symbaton; @@ -213,10 +216,10 @@ dwarf_expr_frame_base_1 (struct symbol *framefunc, CORE_ADDR pc, *start = symbaton->data; } else - *start = NULL; + *length = 0; } - if (*start == NULL) + if (*length == 0) error (_("Could not find the frame base for \"%s\"."), SYMBOL_NATURAL_NAME (framefunc)); } @@ -2788,7 +2791,7 @@ locexpr_tracepoint_var_ref (struct symbol *symbol, struct gdbarch *gdbarch, struct dwarf2_locexpr_baton *dlbaton = SYMBOL_LOCATION_BATON (symbol); unsigned int addr_size = dwarf2_per_cu_addr_size (dlbaton->per_cu); - if (dlbaton->data == NULL || dlbaton->size == 0) + if (dlbaton->size == 0) value->optimized_out = 1; else dwarf2_compile_expr_to_ax (ax, value, gdbarch, addr_size, @@ -2821,11 +2824,8 @@ loclist_read_variable (struct symbol *symbol, struct frame_info *frame) CORE_ADDR pc = frame ? get_frame_address_in_block (frame) : 0; data = dwarf2_find_location_expression (dlbaton, &size, pc); - if (data == NULL) - val = allocate_optimized_out_value (SYMBOL_TYPE (symbol)); - else - val = dwarf2_evaluate_loc_desc (SYMBOL_TYPE (symbol), frame, data, size, - dlbaton->per_cu); + val = dwarf2_evaluate_loc_desc (SYMBOL_TYPE (symbol), frame, data, size, + dlbaton->per_cu); return val; } @@ -2938,7 +2938,7 @@ loclist_tracepoint_var_ref (struct symbol *symbol, struct gdbarch *gdbarch, unsigned int addr_size = dwarf2_per_cu_addr_size (dlbaton->per_cu); data = dwarf2_find_location_expression (dlbaton, &size, ax->scope); - if (data == NULL || size == 0) + if (size == 0) value->optimized_out = 1; else dwarf2_compile_expr_to_ax (ax, value, gdbarch, addr_size, data, data + size, --- a/gdb/dwarf2loc.h +++ b/gdb/dwarf2loc.h @@ -80,10 +80,12 @@ struct value *dwarf2_evaluate_loc_desc (struct type *type, struct dwarf2_locexpr_baton { - /* Pointer to the start of the location expression. */ + /* Pointer to the start of the location expression. Valid only if SIZE is + not zero. */ const gdb_byte *data; - /* Length of the location expression. */ + /* Length of the location expression. For optimized out expressions it is + zero. */ unsigned long size; /* The compilation unit containing the symbol whose location --- a/gdb/dwarf2read.c +++ b/gdb/dwarf2read.c @@ -712,6 +712,8 @@ struct function_range struct dwarf_block { unsigned int size; + + /* Valid only if SIZE is not zero. */ gdb_byte *data; }; @@ -13838,7 +13840,6 @@ dwarf2_fetch_die_location_block (unsigned int offset, { /* DWARF: "If there is no such attribute, then there is no effect.". */ - retval.data = NULL; retval.size = 0; } else if (attr_form_is_section_offset (attr)) @@ -14970,7 +14971,6 @@ dwarf2_symbol_mark_computed (struct attribute *attr, struct symbol *sym, dwarf2_invalid_attrib_class_complaint ("location description", SYMBOL_NATURAL_NAME (sym)); baton->size = 0; - baton->data = NULL; } SYMBOL_COMPUTED_OPS (sym) = &dwarf2_locexpr_funcs; --- a/gdb/testsuite/gdb.dwarf2/dw2-op-call.S +++ b/gdb/testsuite/gdb.dwarf2/dw2-op-call.S @@ -72,10 +72,30 @@ array3: .2byte 3 .uleb128 array3-array1 /* */ 2: + .uleb128 3 /* Abbrev: DW_TAG_variable */ + .ascii "arraycallnoloc\0" /* DW_AT_name */ + .4byte .L2byte_type-.Lcu1_begin /* DW_AT_type */ + .byte 2f - 1f /* DW_AT_location */ +1: .byte 0x99 /* DW_OP_call4 */ + .4byte .Larraynoloc-.Lcu1_begin /* */ +2: + +.Larraynoloc: + .uleb128 4 /* Abbrev: DW_TAG_variable-loclist */ + .ascii "arraynoloc\0" /* DW_AT_name */ + .4byte .L2byte_type-.Lcu1_begin /* DW_AT_type */ + .4byte loclist /* DW_AT_location */ + .byte 0 /* End of children of CU */ .Lcu1_end: +/* Location list. */ + .section .debug_loc +loclist: + /* Location list end. */ + .4byte 0, 0 + /* Abbrev table */ .section .debug_abbrev .Labbrev1_begin: @@ -115,5 +135,17 @@ array3: .2byte 3 .byte 0x0 /* Terminator */ .byte 0x0 /* Terminator */ + .uleb128 4 /* Abbrev code */ + .uleb128 0x34 /* DW_TAG_variable-loclist */ + .byte 0 /* has_children */ + .uleb128 0x3 /* DW_AT_name */ + .uleb128 0x8 /* DW_FORM_string */ + .uleb128 0x49 /* DW_AT_type */ + .uleb128 0x13 /* DW_FORM_ref4 */ + .uleb128 0x2 /* DW_AT_location */ + .uleb128 0x06 /* DW_FORM_data4 */ + .byte 0x0 /* Terminator */ + .byte 0x0 /* Terminator */ + .byte 0x0 /* Terminator */ .byte 0x0 /* Terminator */ --- a/gdb/testsuite/gdb.dwarf2/dw2-op-call.exp +++ b/gdb/testsuite/gdb.dwarf2/dw2-op-call.exp @@ -22,15 +22,17 @@ if {![dwarf2_support]} { } set testfile "dw2-op-call" -set srcfile ${testfile}.S -set executable ${testfile}.x - -if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${objdir}/${subdir}/${executable}" object {nodebug}] != "" } { +if { [prepare_for_testing ${testfile}.exp ${testfile} [list ${testfile}.S main.c] {nodebug}] } { return -1 } -clean_restart $executable - gdb_test "p array1" " = 1" gdb_test "p array2" " = 2" "array2 using DW_OP_call2" gdb_test "p array3" " = 3" "array3 using DW_OP_call4" + +# Location lists need PC. +if ![runto_main] { + return -1 +} +gdb_test "p arraynoloc" " = " +gdb_test "p arraycallnoloc" {Asked for position 0 of stack, stack only has 0 elements on it\.}