From patchwork Sat Feb 23 00:53:23 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Terekhov, Mikhail via Gdb-patches" X-Patchwork-Id: 31568 Received: (qmail 19840 invoked by alias); 23 Feb 2019 00:54:14 -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 19822 invoked by uid 89); 23 Feb 2019 00:54:13 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-26.9 required=5.0 tests=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.2 spammy=H*Ad:U*dblaikie, H*MI:google X-HELO: mail-qt1-f202.google.com Received: from mail-qt1-f202.google.com (HELO mail-qt1-f202.google.com) (209.85.160.202) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Sat, 23 Feb 2019 00:54:12 +0000 Received: by mail-qt1-f202.google.com with SMTP id d13so3712374qth.6 for ; Fri, 22 Feb 2019 16:54:12 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20161025; h=date:message-id:mime-version:subject:from:to:cc :content-transfer-encoding; bh=xpdy2PgIRQ4ARKhkMrk2RMSkwu2LaSrl1VBivleljY0=; b=l5kHA4IEbsDRPZu9rrcC0IGeDaQUhkYgUfzJ51VI6T8VnAhVeqKiRhx9XbWH78TiUI WUQuikiX6VvhUFWGz+jDtnaMeNUdEY9c/MqdkSR2xC7zKM/fxvUdnzCxZSjGPXIz5E9D NHeXbmSPX96VOWxMOYkAwmSb6SN0NGIv0QRnV/bnt6u4vMSFa4TFG4y55S6by5vQDOFM XXG31ope1UzERyjl5+yOwWX6vuQ+zkLbMS8lPxI5+pdG1JzoPLcD0d8jEkw0/7bxkM9h uIAaj7mWLDHtwDCrtDepT7L4oZYMtgAKjLYoyGi7QOUnNA7kdU+d9/MJgMEvGm2UxZCT Gdbg== Date: Fri, 22 Feb 2019 16:53:23 -0800 Message-Id: <20190223005323.188851-1-rupprecht@google.com> Mime-Version: 1.0 Subject: [PATCH] [dwarf2read] Fix crash when loading dwp files: calculate num_sections based on actual section indices, not just the number of sections. X-Patchwork-Original-From: "Jordan Rupprecht via gdb-patches" From: "Terekhov, Mikhail via Gdb-patches" Reply-To: Jordan Rupprecht To: gdb-patches@sourceware.org Cc: echristo@gmail.com, dblaikie@gmail.com, dje@google.com, Jordan Rupprecht When loading dwp files, we create an array of elf sections indexed by the section index in the dwp file. The size of this array is calculated by section_count + 1 (the +1 handling the null section). However, when loading the bfd file, strtab/symtab sections are not added to the list, nor do they increment section_count, so section_count is actually smaller than the number of sections. This happens to work when using GNU dwp, which lays out .debug section first, with sections like .shstrtab coming at the end. Other tools, like llvm-dwp, put .strtab first, and gdb crashes when loading those dwp files. For instance, with the current state of gdb, loading a file like this: $ readelf -SW [ 0] [ 1] .debug_foo PROGBITS ... [ 2] .strtab STRTAB ... ... results in section_count = 2 (.debug is the only thing placed into bfd->sections, so section_count + 1 == 2), and sectp->this_idx = 1 when mapping over .debug_foo in dwarf2_locate_common_dwp_sections, which passes the assertion that 1 < 2. However, using a dwp file produced by llvm-dwp: $ readelf -SW [ 0] [ 1] .strtab STRTAB ... [ 2] .debug_foo PROGBITS ... ... results in section_count = 2 (.debug is the only thing placed into bfd->sections, so section_count + 1 == 2), and sectp->this_idx = 2 when mapping over .debug_foo in dwarf2_locate_common_dwp_sections, which fails the assertion that 2 < 2. This patch changes the calculation of section_count to look at the actual highest this_idx value we see instead of assuming that all strtab/symtab sections come at the end. --- gdb/ChangeLog | 6 ++++++ gdb/dwarf2read.c | 17 +++++++++++++++-- 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 6a551dfa64..c789b34890 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,9 @@ +2019-02-22 Jordan Rupprecht + + * dwarf2read.c (get_largest_section_index): new function + (open_and_init_dwp_file): Call get_largest_section_index to + calculate dwp_file->num_sections. + 2019-02-22 Simon Marchi * MAINTAINERS: Update my email address. diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c index 98f46e0416..07a9d4ea5d 100644 --- a/gdb/dwarf2read.c +++ b/gdb/dwarf2read.c @@ -13182,6 +13182,18 @@ open_dwp_file (struct dwarf2_per_objfile *dwarf2_per_objfile, return NULL; } +/* Return the largest section index */ +static int +get_largest_section_index(bfd *bfd) +{ + int max_sec_idx = 0; + asection *sectp; + for (sectp = bfd->sections; sectp != NULL; sectp = sectp->next) + max_sec_idx = std::max (max_sec_idx, elf_section_data (sectp)->this_idx); + + return max_sec_idx; +} + /* Initialize the use of the DWP file for the current objfile. By convention the name of the DWP file is ${objfile}.dwp. The result is NULL if it can't be found. */ @@ -13230,8 +13242,9 @@ open_and_init_dwp_file (struct dwarf2_per_objfile *dwarf2_per_objfile) std::unique_ptr dwp_file (new struct dwp_file (name, std::move (dbfd))); - /* +1: section 0 is unused */ - dwp_file->num_sections = bfd_count_sections (dwp_file->dbfd) + 1; + /* +1: so that dwp_file->elf_sections[max_idx] is valid */ + dwp_file->num_sections = + get_largest_section_index (dwp_file->dbfd.get()) + 1; dwp_file->elf_sections = OBSTACK_CALLOC (&objfile->objfile_obstack, dwp_file->num_sections, asection *);