From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by sourceware.org (Postfix) with ESMTPS id 72971385E836 for ; Fri, 25 Mar 2022 03:44:28 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 72971385E836 Received: from mimecast-mx02.redhat.com (mx3-rdu2.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-453-6x09fMdNNc2PonkQWwr3Lg-1; Thu, 24 Mar 2022 23:44:21 -0400 X-MC-Unique: 6x09fMdNNc2PonkQWwr3Lg-1 Received: from smtp.corp.redhat.com (int-mx09.intmail.prod.int.rdu2.redhat.com [10.11.54.9]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 5C01F2800F71; Fri, 25 Mar 2022 03:44:21 +0000 (UTC) Received: from f35-1.lan (unknown [10.2.16.88]) by smtp.corp.redhat.com (Postfix) with ESMTP id D0A4C42B940; Fri, 25 Mar 2022 03:44:20 +0000 (UTC) From: Kevin Buettner To: gdb-patches@sourceware.org Subject: [PATCH v2 1/2] [symtab/27831] Fix OBJF_MAINLINE assert Date: Thu, 24 Mar 2022 20:42:53 -0700 Message-Id: <20220325034253.2639930-2-kevinb@redhat.com> In-Reply-To: <20220325034253.2639930-1-kevinb@redhat.com> References: <20220325034253.2639930-1-kevinb@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.85 on 10.11.54.9 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: 8bit Content-Type: text/plain; charset="US-ASCII"; x-default=true X-Spam-Status: No, score=-10.9 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_STOCKGEN, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H4, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_NONE, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 25 Mar 2022 03:44:32 -0000 This commit fixes a bug mentioned by Florian Weimer during the libpthread/ld.so load order discussion from 2021. Florian provided instructions for reproducing the bug here: https://sourceware.org/pipermail/gdb-patches/2021-April/177923.html That particular test does some interesting things involving forks, threads, and thread local storage. Fortunately, none of that is needed to reproduce the problem. I've made a new test case (which is now found in a separate commit) contained in the files gdb.base/add-symbol-file-attach.{c,exp}. The .c file is fairly simple as is the recipe for reproducing the problem. After separately starting the test case and noting the process id, start gdb (w/ no arguments), and do the following to reproduce the assertion failure - for this run, the process id of the separately started add-symbol-file-attach process is 4103218: (gdb) add-symbol-file add-symbol-file-attach add symbol table from file "add-symbol-file-attach" (y or n) y Reading symbols from add-symbol-file-attach... (gdb) attach 4103218 Attaching to process 4103218 Load new symbol table from "/tmp/add-symbol-file-attach"? (y or n) y Reading symbols from /tmp/add-symbol-file-attach... Reading symbols from /lib64/libc.so.6... (No debugging symbols found in /lib64/libc.so.6) Reading symbols from /lib64/ld-linux-x86-64.so.2... (No debugging symbols found in /lib64/ld-linux-x86-64.so.2) 0x00007f502130bf27 in pause () from /lib64/libc.so.6 (gdb) p foo symtab.c:6417: internal-error: CORE_ADDR get_msymbol_address(objfile*, const minimal_symbol*): Assertion `(objf->flags & OBJF_MAINLINE) == 0' failed. A problem internal to GDB has been detected, further debugging may prove unreliable. The add-symbol-file command causes the symbols to be loaded without the SYMFILE_MAINLINE (and hence the OBJFILE_MAINLINE) flags being set. This, in turn, causes the "maybe_copied" flag to be set for the global symbol (named "foo" in the provided test case). The attach command will cause another objfile to be created, but it will reuse the symtabs from the objfile created by add-symbol-file, leading to a situation in which the OBJFILE_MAINLINE flag will be set for the new (attach-created) objfile, however the "maybe_copied" flag will still be set for the global symbol. Had it been loaded anew, this flag would not be set due to OBJFILE_MAINLINE being set for the objfile. At present, the MSYMBOL_VALUE_ADDRESS macro looks like this: #define MSYMBOL_VALUE_ADDRESS(objfile, symbol) \ (((symbol)->maybe_copied) ? get_msymbol_address (objfile, symbol) \ : ((symbol)->value.address \ + (objfile)->section_offsets[(symbol)->section_index ()])) So, we can now see the problem: When the "maybe_copied" flag is set, get_msymbol_address() will be called. However, get_msymbol_address() assumes that it won't be called with the OBF_MAINLINE flag set for the objfile in question. It, in fact, contains an assert() which makes sure that this is the case: gdb_assert ((objf->flags & OBJF_MAINLINE) == 0); (If this assert is removed, then get_msymbol_address() recurses infinitely for the case under consideration.) So, the problem here is that the maybe_copied flag is set for the symbol AND the OBJF_MAINLINE flag is set for the objfile. As noted earlier, this happens due to add-symbol-file being used; this causes the maybe_copied flag to be set. Later, when the attach is performed, OBJF_MAINLINE will be set for that objfile, leading to this unfortunate situation. My first cut at a solution involved adjusting the MSYMBOL_VALUE_ADDRESS macro to include a test of the OBJFILE_MAINLINE flag. However, Simon Marchi, in his review of my patch, suggested a better solution. Simon observed that the 'maybe_copied' flag is (was, after this commit) being set/initialized in record_minimal_symbol() using using the objfile in the context in which the symbol was created. Simon further observed: Today, a single copy is created, as symtabs are shared between objfiles. This means that everything that we store into a symbol must be independent of any objfile. However, the value of the maybe_copied field is dependent on the objfile in the context of which the symbol was created. Meaning that when the symbol is re-used in the context of another objfile, the maybe_copied value is not right in the context of that objfile. So I think it means there isn't a single "is this symbol maybe copied" value, but instead "is this symbol maybe copied, in the context of this given objfile". And the answer is yes or no, depending on whether the objfile is mainline. So maybe_copied should become a method that takes an objfile and returns an answer based on that. [ Simon's full review can be found here: https://sourceware.org/pipermail/gdb-patches/2021-May/178855.html ] Simon also provided a patch which implements this suggestion. The current patch is his work, though I did move and adjust a comment. Lastly, I'll note that this is a strange use case. It's far more common to either let gdb figure out which file to load by itself when attaching, i.e. (gdb) attach 4104360 Attaching to process 4104360 Reading symbols from /tmp/add-symbol-file-attach... Reading symbols from /lib64/libc.so.6... (No debugging symbols found in /lib64/libc.so.6) Reading symbols from /lib64/ld-linux-x86-64.so.2... (No debugging symbols found in /lib64/ld-linux-x86-64.so.2) 0x00007fdb1fc33f27 in pause () from /lib64/libc.so.6 (gdb) p foo $1 = 42 ...or to use the "file" command prior to the attach, like this: (gdb) file add-symbol-file-attach Reading symbols from add-symbol-file-attach... (gdb) attach 4104360 Attaching to program: /tmp/add-symbol-file-attach, process 4104360 Reading symbols from /lib64/libc.so.6... (No debugging symbols found in /lib64/libc.so.6) Reading symbols from /lib64/ld-linux-x86-64.so.2... (No debugging symbols found in /lib64/ld-linux-x86-64.so.2) 0x00007fdb1fc33f27 in pause () from /lib64/libc.so.6 Both of these more common scenarios work perfectly fine; using "add-symbol-file" to load the program to which you will attach isn't recommended as a normal use case. That said, it's bad for gdb to assert, hence this fix. Co-Authored-By: Simon Marchi Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=27831 --- gdb/elfread.c | 8 +------- gdb/symtab.c | 11 ++++++++++- gdb/symtab.h | 19 ++++++++++--------- 3 files changed, 21 insertions(+), 17 deletions(-) diff --git a/gdb/elfread.c b/gdb/elfread.c index 3f2d8b4e233..f21bfaadb69 100644 --- a/gdb/elfread.c +++ b/gdb/elfread.c @@ -213,13 +213,7 @@ record_minimal_symbol (minimal_symbol_reader &reader, if ((bfd_section_flags (bfd_section) & SEC_ALLOC) == SEC_ALLOC) section_index = gdb_bfd_section_index (objfile->obfd, bfd_section); - struct minimal_symbol *result - = reader.record_full (name, copy_name, address, ms_type, section_index); - if ((objfile->flags & OBJF_MAINLINE) == 0 - && (ms_type == mst_data || ms_type == mst_bss)) - result->maybe_copied = 1; - - return result; + return reader.record_full (name, copy_name, address, ms_type, section_index); } /* Read the symbol table of an ELF file. diff --git a/gdb/symtab.c b/gdb/symtab.c index a867e1db9fd..38a69de9fcd 100644 --- a/gdb/symtab.c +++ b/gdb/symtab.c @@ -443,6 +443,15 @@ minimal_symbol::text_p () const || type == mst_file_text; } +/* See symtab.h. */ + +bool +minimal_symbol::maybe_copied (objfile *objfile) const +{ + return ((objfile->flags & OBJF_MAINLINE) == 0 + && (this->type == mst_data || this->type == mst_bss)); +} + /* See whether FILENAME matches SEARCH_NAME using the rule that we advertise to the user. (The manual's description of linespecs describes what we advertise). Returns true if they match, false @@ -6595,7 +6604,7 @@ get_symbol_address (const struct symbol *sym) CORE_ADDR get_msymbol_address (struct objfile *objf, const struct minimal_symbol *minsym) { - gdb_assert (minsym->maybe_copied); + gdb_assert (minsym->maybe_copied (objf)); gdb_assert ((objf->flags & OBJF_MAINLINE) == 0); const char *linkage_name = minsym->linkage_name (); diff --git a/gdb/symtab.h b/gdb/symtab.h index d12eee6e9d8..dd6b70b8719 100644 --- a/gdb/symtab.h +++ b/gdb/symtab.h @@ -704,14 +704,6 @@ struct minimal_symbol : public general_symbol_info the object file format may not carry that piece of information. */ unsigned int has_size : 1; - /* For data symbols only, if this is set, then the symbol might be - subject to copy relocation. In this case, a minimal symbol - matching the symbol's linkage name is first looked for in the - main objfile. If found, then that address is used; otherwise the - address in this symbol is used. */ - - unsigned maybe_copied : 1; - /* Non-zero if this symbol ever had its demangled name set (even if it was set to NULL). */ unsigned int name_set : 1; @@ -733,6 +725,15 @@ struct minimal_symbol : public general_symbol_info /* True if MSYMBOL is of some text type. */ bool text_p () const; + + /* For data symbols only, given an objfile, if 'maybe_copied' + evaluates to 'true' for that objfile, then the symbol might be + subject to copy relocation. In this case, a minimal symbol + matching the symbol's linkage name is first looked for in the + main objfile. If found, then that address is used; otherwise the + address in this symbol is used. */ + + bool maybe_copied (objfile *objfile) const; }; /* Return the address of MINSYM, which comes from OBJF. The @@ -762,7 +763,7 @@ extern CORE_ADDR get_msymbol_address (struct objfile *objf, /* The relocated address of the minimal symbol, using the section offsets from OBJFILE. */ #define MSYMBOL_VALUE_ADDRESS(objfile, symbol) \ - (((symbol)->maybe_copied) ? get_msymbol_address (objfile, symbol) \ + (((symbol)->maybe_copied (objfile)) ? get_msymbol_address (objfile, symbol) \ : ((symbol)->value.address \ + (objfile)->section_offsets[(symbol)->section_index ()])) /* For a bound minsym, we can easily compute the address directly. */ -- 2.35.1