From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 11164 invoked by alias); 3 Nov 2011 16:12:45 -0000 Received: (qmail 11148 invoked by uid 22791); 3 Nov 2011 16:12:42 -0000 X-SWARE-Spam-Status: No, hits=-1.7 required=5.0 tests=AWL,BAYES_00,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,RCVD_IN_DNSWL_NONE,TW_BJ X-Spam-Check-By: sourceware.org Received: from caibbdcaaaaf.dreamhost.com (HELO homiemail-a40.g.dreamhost.com) (208.113.200.5) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Thu, 03 Nov 2011 16:12:27 +0000 Received: from homiemail-a40.g.dreamhost.com (localhost [127.0.0.1]) by homiemail-a40.g.dreamhost.com (Postfix) with ESMTP id 9A61574C094; Thu, 3 Nov 2011 09:12:21 -0700 (PDT) Received: from redwood.eagercon.com (c-76-102-3-160.hsd1.ca.comcast.net [76.102.3.160]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) (Authenticated sender: eager@eagerm.com) by homiemail-a40.g.dreamhost.com (Postfix) with ESMTPSA id F328B74C08B; Thu, 3 Nov 2011 09:12:09 -0700 (PDT) Message-ID: <4EB2BD58.3080003@eagerm.com> Date: Thu, 03 Nov 2011 16:12:00 -0000 From: Michael Eager User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:7.0) Gecko/20110927 Thunderbird/7.0 MIME-Version: 1.0 To: "gdb-patches@sourceware.org" CC: Jan Kratochvil Subject: SEGV in dwarf2read.c -- gdb-7.2 Content-Type: multipart/mixed; boundary="------------040904050100040501080509" 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-11/txt/msg00075.txt.bz2 This is a multi-part message in MIME format. --------------040904050100040501080509 Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit Content-length: 1601 I ran into a SEGV in in gdb-7.2 in dwarf_expr_eval() (actually one of the functions it calls) which is called from dwarf2_evaluate_loc_desc_full(). This was caused by the per_cu->cu==NULL. The circumstances which triggered this SEGV is printing a huge structure (four or five pages of output) followed by a backtrace. While printing the struct, dwarf2_fetch_die_location_block() is called multiple times, which calls age_cached_comp_units() which removes CU data from the cache. When doing the backtrace, location descriptions are referenced and eventually a NULL per_cu->cu is dereferenced. I created the attached patch fixes the problem in gdb-7.2 by adding a new function dwarf2_read_comp_unit_if_needed() which reloads the CU data and adds it to the cache. I also modified dwarf2_per_cu_addr_size() and dwarf2_per_cu_addr_size() to use this function rather than read the CU header into a temporary. When I tried to apply this to the head, I discovered that these functions had been refactored adding a function per_cu_header_read_in() which read in the CU header into a temporary. I can rework the patch to exclude the conflicting changes, but this raises a question: Is there a reason to read the CU header into a temporary data area rather than reload it using load_full_comp_unit() which will add it to the CU cache? I noticed that a TRY_CATCH was added to dwarf2_evaluate_loc_desc_full() which would catch this SEGV, but (it seems to me, incorrectly) indicate that debug data was not available. -- Michael Eager eager@eagercon.com 1960 Park Blvd., Palo Alto, CA 94306 650-325-8077 --------------040904050100040501080509 Content-Type: text/x-patch; name="gdb-cu-segv.patch" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="gdb-cu-segv.patch" Content-length: 3370 diff -u gdb/dwarf2loc.c /users/meager/ws/gdb-bi-endian/src/gdb-7.2/gdb/gdb/dwarf2loc.c --- gdb/dwarf2loc.c Fri Oct 28 11:43:19 2011 +++ /users/meager/ws/gdb-bi-endian/src/gdb-7.2/gdb/gdb/dwarf2loc.c Fri Oct 28 11:03:40 2011 @@ -919,6 +919,7 @@ ctx->get_tls_address = dwarf_expr_tls_address; ctx->dwarf_call = dwarf_expr_dwarf_call; + dwarf2_read_comp_unit_if_needed (per_cu); dwarf_expr_eval (ctx, data, size); if (ctx->num_pieces > 0) { diff -u gdb/dwarf2loc.h /users/meager/ws/gdb-bi-endian/src/gdb-7.2/gdb/gdb/dwarf2loc.h --- gdb/dwarf2loc.h Wed Nov 17 17:23:58 2010 +++ /users/meager/ws/gdb-bi-endian/src/gdb-7.2/gdb/gdb/dwarf2loc.h Fri Oct 28 11:03:05 2011 @@ -33,6 +33,10 @@ returned. */ struct objfile *dwarf2_per_cu_objfile (struct dwarf2_per_cu_data *cu); +/* Read in CU if needed. */ + +void dwarf2_read_comp_unit_if_needed (struct dwarf2_per_cu_data *per_cu); + /* Return the address size given in the compilation unit header for CU. */ CORE_ADDR dwarf2_per_cu_addr_size (struct dwarf2_per_cu_data *cu); diff -u gdb/dwarf2read.c /users/meager/ws/gdb-bi-endian/src/gdb-7.2/gdb/gdb/dwarf2read.c --- gdb/dwarf2read.c Fri Oct 28 11:43:19 2011 +++ /users/meager/ws/gdb-bi-endian/src/gdb-7.2/gdb/gdb/dwarf2read.c Fri Oct 28 11:11:58 2011 @@ -12116,48 +12116,34 @@ return objfile; } -/* Return the address size given in the compilation unit header for CU. */ +/* Read in CU if needed. */ -CORE_ADDR -dwarf2_per_cu_addr_size (struct dwarf2_per_cu_data *per_cu) +void +dwarf2_read_comp_unit_if_needed (struct dwarf2_per_cu_data *per_cu) { - if (per_cu->cu) - return per_cu->cu->header.addr_size; - else + if (!per_cu->cu) { - /* If the CU is not currently read in, we re-read its header. */ struct objfile *objfile = per_cu->psymtab->objfile; - struct dwarf2_per_objfile *per_objfile - = objfile_data (objfile, dwarf2_objfile_data_key); - gdb_byte *info_ptr = per_objfile->info.buffer + per_cu->offset; - struct comp_unit_head cu_header; - - memset (&cu_header, 0, sizeof cu_header); - read_comp_unit_head (&cu_header, info_ptr, objfile->obfd); - return cu_header.addr_size; + load_full_comp_unit (per_cu, objfile); } } +/* Return the address size given in the compilation unit header for CU. */ + +CORE_ADDR +dwarf2_per_cu_addr_size (struct dwarf2_per_cu_data *per_cu) +{ + dwarf2_read_comp_unit_if_needed (per_cu); + return per_cu->cu->header.addr_size; +} + /* Return the offset size given in the compilation unit header for CU. */ int dwarf2_per_cu_offset_size (struct dwarf2_per_cu_data *per_cu) { - if (per_cu->cu) - return per_cu->cu->header.offset_size; - else - { - /* If the CU is not currently read in, we re-read its header. */ - struct objfile *objfile = per_cu->psymtab->objfile; - struct dwarf2_per_objfile *per_objfile - = objfile_data (objfile, dwarf2_objfile_data_key); - gdb_byte *info_ptr = per_objfile->info.buffer + per_cu->offset; - struct comp_unit_head cu_header; - - memset (&cu_header, 0, sizeof cu_header); - read_comp_unit_head (&cu_header, info_ptr, objfile->obfd); - return cu_header.offset_size; - } + dwarf2_read_comp_unit_if_needed (per_cu); + return per_cu->cu->header.offset_size; } /* Return the text offset of the CU. The returned offset comes from --------------040904050100040501080509--