From patchwork Fri Aug 21 21:24:22 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jan Kratochvil X-Patchwork-Id: 8380 Received: (qmail 124015 invoked by alias); 21 Aug 2015 21:24:33 -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 124001 invoked by uid 89); 21 Aug 2015 21:24:31 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.2 required=5.0 tests=AWL, BAYES_50, KAM_LAZY_DOMAIN_SECURITY, RP_MATCHES_RCVD, SPF_HELO_PASS autolearn=no version=3.3.2 X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-GCM-SHA384 encrypted) ESMTPS; Fri, 21 Aug 2015 21:24:27 +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 (Postfix) with ESMTPS id C2D9E8E4F9 for ; Fri, 21 Aug 2015 21:24:25 +0000 (UTC) Received: from host1.jankratochvil.net (ovpn-116-22.ams2.redhat.com [10.36.116.22]) by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id t7LLONT8031063 for ; Fri, 21 Aug 2015 17:24:23 -0400 Subject: [PATCH v12 32/32] Support build-id for main executables From: Jan Kratochvil To: gdb-patches@sourceware.org Date: Fri, 21 Aug 2015 23:24:22 +0200 Message-ID: <20150821212422.6673.70440.stgit@host1.jankratochvil.net> In-Reply-To: <20150821212006.6673.35100.stgit@host1.jankratochvil.net> References: <20150821212006.6673.35100.stgit@host1.jankratochvil.net> User-Agent: StGit/0.17.1-dirty MIME-Version: 1.0 X-IsSubscribed: yes Hi, make all the existing shlibs build-id functionality working also for the main executables. I think target_so_ops::open_symbol_file_object() is already replaced by what exec_file_and_symbols_resync(), target_pid_to_exec_file() etc. does but open_symbol_file_object() has been forgotten. This patch adds target_so_ops::main_build_id() which could be possibly marged with open_symbol_file_object() but I made it a separate function as I think it is easier to rather remove target_so_ops::open_symbol_file_object(). Jan gdb/ChangeLog 2015-08-20 Jan Kratochvil * NEWS (Changes since GDB 7.10): Mention also main-build-id. * build-id.c (build_id_verify): Add parameter advice. * build-id.h (build_id_verify): Likewise. * dwarf2read.c (dwarf2_get_dwz_file): Update build_id_verify caller. * exec.c: Include build-id.h. (exec_file_and_symbols_resync): Detect and use build-id by solib_main_build_id. * features/library-list-svr4.dtd: Add main-build-id. * solib-svr4.c (struct svr4_info, struct svr4_library_list): Add fields main_build_idsz and main_build_id. (hex2bin_allocate): Generalize messages to binary files. (svr4_library_list_start_list): Parse main-build-id. (svr4_library_list_attributes): Add main-build-id. (svr4_current_sos_direct): Set svr4_info main_build_id*. (svr4_main_build_id): New function. (svr4_clear_solib): Clear svr4_info main_build_id*. (_initialize_svr4_solib): Install svr4_main_build_id. * solib.c (solib_main_build_id): New function. * solist.h (struct target_so_ops): Add method main_build_id. (solib_main_build_id): New prototype. * source.c (file_location_from_filename): Update build_id_verify caller. gdb/gdbserver/ChangeLog 2015-08-20 Jan Kratochvil * linux-low.c (linux_qxfer_libraries_svr4): Print main-build-id. gdb/doc/ChangeLog 2015-08-20 Jan Kratochvil * gdb.texinfo (Files): Add 'set validate-build-id' and 'show validate-build-id'. gdb/testsuite/ChangeLog 2015-08-20 Jan Kratochvil * gdb.base/main-mismatch-mod.c: New file. * gdb.base/main-mismatch.c: New file. * gdb.base/main-mismatch.exp: New file. --- gdb/testsuite/gdb.base/main-mismatch-mod.c | 39 +++++++ gdb/testsuite/gdb.base/main-mismatch.c | 39 +++++++ gdb/testsuite/gdb.base/main-mismatch.exp | 158 ++++++++++++++++++++++++++++ 3 files changed, 236 insertions(+) create mode 100644 gdb/testsuite/gdb.base/main-mismatch-mod.c create mode 100644 gdb/testsuite/gdb.base/main-mismatch.c create mode 100644 gdb/testsuite/gdb.base/main-mismatch.exp diff --git a/gdb/NEWS b/gdb/NEWS index a45aaa6..28c319e 100644 --- a/gdb/NEWS +++ b/gdb/NEWS @@ -52,8 +52,8 @@ show validate-build-id * New features in the GDB remote stub, GDBserver ** library-list-svr4 contains also optional attribute 'build-id' for - each library. GDB does not load library with build-id that - does not match such attribute. + each library and one optional attribute 'main-build-id'. GDB does + not load binaries with build-id that does not match such attribute. *** Changes in GDB 7.10 diff --git a/gdb/build-id.c b/gdb/build-id.c index 48839cc..289c356 100644 --- a/gdb/build-id.c +++ b/gdb/build-id.c @@ -62,7 +62,7 @@ build_id_bfd_get (bfd *abfd) /* See build-id.h. */ int -build_id_verify (bfd *abfd, size_t check_len, const bfd_byte *check) +build_id_verify (bfd *abfd, size_t check_len, const bfd_byte *check, int advice) { const struct bfd_build_id *found; char *message, *check_hex; @@ -93,9 +93,12 @@ build_id_verify (bfd *abfd, size_t check_len, const bfd_byte *check) return 1; back_to = make_cleanup (xfree, message); - warning (_("Symbol file \"%s\" could not be validated (%s) and " - "will be ignored; or use 'set validate-build-id off'."), - bfd_get_filename (abfd), message); + if (!advice) + warning ("%s", message); + else + warning (_("Symbol file \"%s\" could not be validated (%s) and " + "will be ignored; or use 'set validate-build-id off'."), + bfd_get_filename (abfd), message); do_cleanups (back_to); return 0; } diff --git a/gdb/build-id.h b/gdb/build-id.h index bb93df2..bb5e65d 100644 --- a/gdb/build-id.h +++ b/gdb/build-id.h @@ -25,10 +25,11 @@ extern const struct bfd_build_id *build_id_bfd_get (bfd *abfd); /* Return true if ABFD has NT_GNU_BUILD_ID matching the CHECK value. - Otherwise, issue a warning and return false. */ + Otherwise, issue a warning and return false. Boolean ADVICE says whether + the warning should suggest to user there is the 'validate-build-id' flag. */ -extern int build_id_verify (bfd *abfd, - size_t check_len, const bfd_byte *check); +extern int build_id_verify (bfd *abfd, size_t check_len, const bfd_byte *check, + int advice); extern struct file_location build_id_to_file (size_t build_id_len, const bfd_byte *build_id, diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index fa30007..40f0f14 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -18109,6 +18109,41 @@ libraries that were loaded by explicit user requests are not discarded. @end table +@table @code +@kindex set validate-build-id +@cindex override @value{GDBN} build-id check +@item set validate-build-id @var{mode} +Setting to override @value{GDBN} build-id check. + +Inferior binaries (shared libraries or main executable) and symbol files +(for all of those) may contain unique build-id. @value{GDBN} expects +the build-ids of each binary and its corresponding symbol file to be +identical. If they are not identical, then by default @value{GDBN} will +@value{GDBN} will ignore symbol files with non-matching build-id while +printing: + +@smallexample + warning: Symbol file "libfoo.so.1" could not be validated (inferior + build ID 66f87872 is not identical to symbol file "libfoo.so.1" build + ID df81e8db) and will be ignored; or use 'set validate-build-id off'. +@end smallexample + +Turning off this setting would load such symbol file without any warning. + +If remote build-id is present but it does not match local build-id (or local +build-id is not present) then this setting enables (@var{mode} is @code{off}) or +disables (@var{mode} is @code{on}) loading of such symbol file. On systems +where build-id is not present in the remote system this setting has no effect. +The default value is @code{on}. + +Loading non-matching symbol file may confuse debugging including breakage +of backtrace output. + +@kindex show validate-build-id +@item show validate-build-id +Display the current mode of build-id check override. +@end table + Sometimes you may wish that @value{GDBN} stops and gives you control when any of shared library events happen. The best way to do this is to use @code{catch load} and @code{catch unload} (@pxref{Set @@ -39763,7 +39798,9 @@ address the file was prelinked to during the library load. Additionally the single @code{main-lm} attribute specifies address of @code{struct link_map} used for the main executable. This parameter is used -for TLS access and its presence is optional. +for TLS access and its presence is optional. Similarly the single +@code{main-build-id} optional attribute specifies hex encoded +@code{NT_GNU_BUILD_ID} note for the main executable. @value{GDBN} must be linked with the Expat library to support XML SVR4 library lists. @xref{Expat}. @@ -39772,7 +39809,8 @@ A simple memory map, with two loaded libraries (which do not use prelink), looks like this: @smallexample - + - - + + + diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c index 3fb446f..d6054e9 100644 --- a/gdb/dwarf2read.c +++ b/gdb/dwarf2read.c @@ -2498,7 +2498,7 @@ dwarf2_get_dwz_file (void) dwz_bfd = gdb_bfd_open (filename, gnutarget, -1); if (dwz_bfd != NULL) { - if (!build_id_verify (dwz_bfd, buildid_len, buildid)) + if (!build_id_verify (dwz_bfd, buildid_len, buildid, 1 /* advice */)) { gdb_bfd_unref (dwz_bfd); dwz_bfd = NULL; diff --git a/gdb/exec.c b/gdb/exec.c index 056516b..dc39ed2 100644 --- a/gdb/exec.c +++ b/gdb/exec.c @@ -35,6 +35,7 @@ #include "progspace.h" #include "gdb_bfd.h" #include "gcore.h" +#include "build-id.h" #include #include "readline/readline.h" @@ -143,11 +144,16 @@ exec_file_and_symbols_resync (struct inferior *inf, int from_tty) { char *exec_file, *full_exec_path = NULL; struct cleanup *old_chain = save_current_program_space (); + size_t build_idsz; + gdb_byte *build_id; /* Switch over temporarily, while reading executable and symbols. */ set_current_program_space (inf->pspace); + solib_main_build_id (&build_idsz, &build_id); + make_cleanup (xfree, build_id); + /* Try to determine a filename from the process itself. */ exec_file = target_pid_to_exec_file (inf->pid); if (exec_file != NULL) @@ -155,8 +161,7 @@ exec_file_and_symbols_resync (struct inferior *inf, int from_tty) /* If gdb_sysroot is not empty and the discovered filename is absolute then prefix the filename with gdb_sysroot. */ if (*gdb_sysroot != '\0' && IS_ABSOLUTE_PATH (exec_file)) - full_exec_path = exec_file_find (exec_file, 0 /* build_idsz */, - NULL /* build_id */, NULL); + full_exec_path = exec_file_find (exec_file, build_idsz, build_id, NULL); if (full_exec_path == NULL) { @@ -167,8 +172,8 @@ exec_file_and_symbols_resync (struct inferior *inf, int from_tty) Attempt to qualify the filename against the source path. (If that fails, we'll just fall back on the original filename. Not much more we can do...) */ - if (!source_full_path_of (exec_file, 0 /* build_idsz */, - NULL /* build_id */, &full_exec_path)) + if (!source_full_path_of (exec_file, build_idsz, build_id, + &full_exec_path)) full_exec_path = xstrdup (exec_file); } } @@ -179,6 +184,7 @@ exec_file_and_symbols_resync (struct inferior *inf, int from_tty) warning (_("Detected exec-file mismatch on %s. Running %s; Loaded %s"), target_pid_to_str (pid_to_ptid (inf->pid)), full_exec_path, exec_filename); + build_id_verify (exec_bfd, build_idsz, build_id, 0 /* advice */); reopen_exec_file (); } else if (full_exec_path != NULL) @@ -194,6 +200,9 @@ exec_file_and_symbols_resync (struct inferior *inf, int from_tty) "Running %s; Loaded %s"), target_pid_to_str (pid_to_ptid (inf->pid)), full_exec_path, symbol_filename); + + build_id_verify (symfile_objfile->obfd, build_idsz, build_id, + 0 /* advice */); } else if (full_exec_path != NULL) symbol_file_add_main (0, full_exec_path, from_tty); diff --git a/gdb/features/library-list-svr4.dtd b/gdb/features/library-list-svr4.dtd index 5741f03..27799a6 100644 --- a/gdb/features/library-list-svr4.dtd +++ b/gdb/features/library-list-svr4.dtd @@ -6,8 +6,9 @@ - - + + + diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c index ee8563e..6783dc2 100644 --- a/gdb/gdbserver/linux-low.c +++ b/gdb/gdbserver/linux-low.c @@ -6915,8 +6915,25 @@ linux_qxfer_libraries_svr4 (const char *annex, unsigned char *readbuf, exited above due to failed get_r_debug. */ if (lm_prev == 0) { + const char *hex_enc_build_id = get_hex_build_id (l_addr, l_ld, &data); + sprintf (p, " main-lm=\"0x%lx\"", (unsigned long) lm_addr); p = p + strlen (p); + + if (hex_enc_build_id != NULL) + { + while (allocated + < p - document + 200 + strlen (hex_enc_build_id)) + { + /* Expand to guarantee sufficient storage. */ + uintptr_t document_len = p - document; + + document = xrealloc (document, 2 * allocated); + allocated *= 2; + p = document + document_len; + } + p += sprintf (p, " main-build-id=\"%s\"", hex_enc_build_id); + } } else { diff --git a/gdb/solib-svr4.c b/gdb/solib-svr4.c index 858b942..fd83128 100644 --- a/gdb/solib-svr4.c +++ b/gdb/solib-svr4.c @@ -358,6 +358,8 @@ struct svr4_info /* Load map address for the main executable. */ CORE_ADDR main_lm_addr; + size_t main_build_idsz; + gdb_byte *main_build_id; CORE_ADDR interp_text_sect_low; CORE_ADDR interp_text_sect_high; @@ -1087,6 +1089,9 @@ struct svr4_library_list /* Inferior address of struct link_map used for the main executable. It is NULL if not known. */ CORE_ADDR main_lm; + + size_t main_build_idsz; + gdb_byte *main_build_id; }; /* Implementation for target_so_ops.free_so. */ @@ -1175,13 +1180,13 @@ hex2bin_allocate (const char *hex, gdb_byte **binp, size_t *binszp, hex_len = strlen (hex); if (hex_len == 0) { - warning (_("Shared library \"%s\" received empty build-id " + warning (_("Binary file \"%s\" received empty build-id " "from gdbserver"), filename); return; } if ((hex_len & 1U) != 0) { - warning (_("Shared library \"%s\" received odd number " + warning (_("Binary file \"%s\" received odd number " "of build-id \"%s\" hex characters from gdbserver"), filename, hex); return; @@ -1191,7 +1196,7 @@ hex2bin_allocate (const char *hex, gdb_byte **binp, size_t *binszp, *binszp = hex2bin (hex, *binp, binsz); if (*binszp != binsz) { - warning (_("Shared library \"%s\" received invalid " + warning (_("Binary file \"%s\" received invalid " "build-id \"%s\" hex character at encoded byte " "position %s (first as 0) from gdbserver"), filename, hex, pulongest (*binszp)); @@ -1245,6 +1250,10 @@ svr4_library_list_start_list (struct gdb_xml_parser *parser, struct svr4_library_list *list = user_data; const char *version = xml_find_attribute (attributes, "version")->value; struct gdb_xml_value *main_lm = xml_find_attribute (attributes, "main-lm"); + const struct gdb_xml_value *const att_main_build_id + = xml_find_attribute (attributes, "main-build-id"); + const char *const main_hex_build_id = (att_main_build_id + ? att_main_build_id->value : NULL); if (strcmp (version, "1.0") != 0) gdb_xml_error (parser, @@ -1253,6 +1262,8 @@ svr4_library_list_start_list (struct gdb_xml_parser *parser, if (main_lm) list->main_lm = *(ULONGEST *) main_lm->value; + hex2bin_allocate (main_hex_build_id, &list->main_build_id, + &list->main_build_idsz, _("main executable")); } /* The allowed elements and attributes for an XML library list. @@ -1282,6 +1293,7 @@ static const struct gdb_xml_attribute svr4_library_list_attributes[] = { { "version", GDB_XML_AF_NONE, NULL, NULL }, { "main-lm", GDB_XML_AF_OPTIONAL, gdb_xml_parse_attr_ulongest, NULL }, + { "main-build-id", GDB_XML_AF_OPTIONAL, NULL, NULL }, { NULL, GDB_XML_AF_NONE, NULL, NULL } }; @@ -1509,15 +1521,24 @@ svr4_current_sos_direct (struct svr4_info *info) Unfortunately statically linked inferiors will also fall back through this suboptimal code path. */ + library_list.main_build_id = NULL; + library_list.main_build_idsz = 0; info->using_xfer = svr4_current_sos_via_xfer_libraries (&library_list, NULL); if (info->using_xfer) { if (library_list.main_lm) info->main_lm_addr = library_list.main_lm; + if (library_list.main_build_id != NULL) + { + xfree (info->main_build_id); + info->main_build_id = library_list.main_build_id; + info->main_build_idsz = library_list.main_build_idsz; + } return library_list.head ? library_list.head : svr4_default_sos (); } + xfree (library_list.main_build_id); /* Always locate the debug struct, in case it has moved. */ info->debug_base = 0; @@ -1576,6 +1597,25 @@ svr4_current_sos_1 (void) return svr4_current_sos_direct (info); } +/* Implement svr4_so_ops's target_so_ops method main_build_id. */ + +static void +svr4_main_build_id (size_t *build_idszp, gdb_byte **build_idp) +{ + struct svr4_info *info = get_svr4_info (); + + /* If the solib list has been read and stored by the probes + interface then even main_build_id should be valid there. */ + if (info->solib_list == NULL) + svr4_current_sos_direct (info); + + *build_idszp = info->main_build_idsz; + if (*build_idszp == 0) + *build_idp = NULL; + else + *build_idp = xmemdup (info->main_build_id, *build_idszp, *build_idszp); +} + /* Implement the "current_sos" target_so_ops method. */ static struct so_list * @@ -3125,6 +3165,9 @@ svr4_clear_solib (void) info->debug_loader_offset = 0; xfree (info->debug_loader_name); info->debug_loader_name = NULL; + xfree (info->main_build_id); + info->main_build_id = NULL; + info->main_build_idsz = 0; } /* Clear any bits of ADDR that wouldn't fit in a target-format @@ -3336,6 +3379,7 @@ _initialize_svr4_solib (void) svr4_so_ops.special_symbol_handling = svr4_special_symbol_handling; svr4_so_ops.current_sos = svr4_current_sos; svr4_so_ops.open_symbol_file_object = open_symbol_file_object; + svr4_so_ops.main_build_id = svr4_main_build_id; svr4_so_ops.in_dynsym_resolve_code = svr4_in_dynsym_resolve_code; svr4_so_ops.bfd_open = solib_bfd_open; svr4_so_ops.lookup_lib_global_symbol = elf_lookup_lib_symbol; diff --git a/gdb/solib.c b/gdb/solib.c index 906cc5c..616cbc1 100644 --- a/gdb/solib.c +++ b/gdb/solib.c @@ -1669,6 +1669,20 @@ solib_global_lookup (struct objfile *objfile, return (struct block_symbol) {NULL, NULL}; } +/* See solist.h. */ + +void +solib_main_build_id (size_t *build_idszp, gdb_byte **build_idp) +{ + const struct target_so_ops *ops = ops = solib_ops (target_gdbarch ()); + + if (ops->main_build_id != NULL) + return ops->main_build_id (build_idszp, build_idp); + + *build_idszp = 0; + *build_idp = NULL; +} + /* Lookup the value for a specific symbol from dynamic symbol table. Look up symbol from ABFD. MATCH_SYM is a callback function to determine whether to pick up a symbol. DATA is the input of this callback diff --git a/gdb/solist.h b/gdb/solist.h index 34af30f..2947c6a 100644 --- a/gdb/solist.h +++ b/gdb/solist.h @@ -135,6 +135,13 @@ struct target_so_ops catch_errors requires a pointer argument. */ int (*open_symbol_file_object) (void *from_ttyp); + /* Report build-id of the main executable. Both BUILD_IDSZP and + BUILD_IDP must not be NULL. If returned *BUILD_IDSZP is zero + build-id is not known. Returned *BUILD_IDP must be xfree-d by + the caller. This pointer can be NULL, in which case this + functionality is not supported for this target. */ + void (*main_build_id) (size_t *build_idszp, gdb_byte **build_idp); + /* Determine if PC lies in the dynamic symbol resolution code of the run time loader. */ int (*in_dynsym_resolve_code) (CORE_ADDR pc); @@ -212,4 +219,7 @@ struct block_symbol solib_global_lookup (struct objfile *objfile, const char *name, const domain_enum domain); +/* See target_so_ops's main_build_id. */ +void solib_main_build_id (size_t *build_idszp, gdb_byte **build_idp); + #endif diff --git a/gdb/source.c b/gdb/source.c index e5684da..6842c52 100644 --- a/gdb/source.c +++ b/gdb/source.c @@ -916,7 +916,7 @@ file_location_from_filename (const char *filename, enum openp_flags opts, return file; } - if (!build_id_verify (file.abfd, build_idsz, build_id)) + if (!build_id_verify (file.abfd, build_idsz, build_id, 1 /* advice */)) { do_cleanups (back_to); file_location_enoent (&file); diff --git a/gdb/testsuite/gdb.base/main-mismatch-mod.c b/gdb/testsuite/gdb.base/main-mismatch-mod.c new file mode 100644 index 0000000..83d0710 --- /dev/null +++ b/gdb/testsuite/gdb.base/main-mismatch-mod.c @@ -0,0 +1,39 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2015 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +int _bar = 21; + +int +bar (void) +{ + return 42 - _bar; +} + +int +foo (void) +{ + return 24 + bar(); +} + +int +main (void) +{ + sleep (60); + return 0; +} diff --git a/gdb/testsuite/gdb.base/main-mismatch.c b/gdb/testsuite/gdb.base/main-mismatch.c new file mode 100644 index 0000000..8ea17dc --- /dev/null +++ b/gdb/testsuite/gdb.base/main-mismatch.c @@ -0,0 +1,39 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2015 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +#include + +int _bar = 42; + +int +bar (void) +{ + return _bar + 21; +} + +int +foo (void) +{ + return _bar; +} + +int +main (void) +{ + sleep (60); + return 0; +} diff --git a/gdb/testsuite/gdb.base/main-mismatch.exp b/gdb/testsuite/gdb.base/main-mismatch.exp new file mode 100644 index 0000000..1aefab0 --- /dev/null +++ b/gdb/testsuite/gdb.base/main-mismatch.exp @@ -0,0 +1,158 @@ +# Copyright 2015 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . */ + +standard_testfile + +if [is_remote target] { + untested "only local remote is currently supported" + return -1 +} +if [is_remote host] { + untested "only local host is currently supported" + return -1 +} +if [target_info exists use_gdb_stub] { + untested "only extended-remote target is supported for this test" + return -1 +} + +clean_restart + +if ![gdb_is_target_remote] { + untested "only gdbserver supports build-id reporting" + return -1 +} +if ![target_is_gdbserver] { + untested "only FSF gdbserver supports build-id reporting" + return -1 +} + +# Test overview: +# generate two executable. One that will be used by the process +# and another, modified, that will be found by gdb. Gdb should +# detect the mismatch and refuse to use mismatched executable. + +# First version of the object. +set srcmainfilerun ${testfile}.c + +# Modified version of the object. +# Code in -mod.c is tuned so it gives a mismatch. +set srcmainfilegdb ${testfile}-mod.c + +# So file name: +set binmainfilebase {testfile} + +# Setup run directory (where program is run from) +# It contains the right executable. +set binmainfiledirrun [standard_output_file ${testfile}_wd] +set binmainfilerun ${binmainfiledirrun}/${binmainfilebase} + +# Second executable version is in current directory, '-mod' version. +set binmainfiledirgdb [standard_output_file ""] +set binmainfilegdb ${binmainfiledirgdb}/${binmainfilebase} + +file delete -force -- "${binmainfiledirrun}" +file mkdir "${binmainfiledirrun}" + +set exec_opts {} +lappend exec_opts "additional_flags=-DDIRNAME\=\"${binmainfiledirrun}\"" +lappend exec_opts "debug" +lappend exec_opts "ldflags=-Wl,--build-id" + +if { [build_executable $testfile.exp $binmainfilerun $srcmainfilerun $exec_opts] != 0 } { + return -1 +} +if { [build_executable $testfile.exp $binmainfilegdb $srcmainfilegdb $exec_opts] != 0 } { + return -1 +} + +set test_spawn_id [spawn_wait_for_attach $binmainfilerun] +set testpid [spawn_id_get_pid $test_spawn_id] + +file copy -force $binmainfilerun $binmainfilerun-backup +file copy -force $binmainfilegdb $binmainfilerun + +with_test_prefix "forced wrong executable" { + clean_restart $binmainfilerun + + set test "attach" + gdb_test_multiple "attach $testpid" "$test" { + -re "Attaching to program: .*\r\nwarning: Detected exec-file mismatch .*\r\nwarning: inferior build ID .*\r\n$gdb_prompt $" { + pass "$test" + } + } + + gdb_test "detach" +} + +with_test_prefix "unavailable autodetected executable" { + clean_restart + + set test "attach" + gdb_test_multiple "attach $testpid" "$test" { + -re "Attaching to process $testpid\r\n.*\r\n$gdb_prompt $" { + pass "$test" + } + } + + set test "bt" + gdb_test_multiple $test $test { + -re " in main \[^\r\n\]*\r\n$gdb_prompt $" { + fail $test + } + -re "\r\n$gdb_prompt $" { + pass $test + } + } + + gdb_test "detach" +} + +# Test locating file by its build-id - if the regular filename does not match. +# build-id file has to be a symlink - otherwise so_list->so_name shown in 'info +# sharedlibrary' would contain the build-id hash and not the library name. +set build_id_debug_relative [build_id_debug_filename_get $binmainfilerun-backup] +if { ![regexp {^(.*)\.debug$} $build_id_debug_relative trash build_id_relative] } { + fail "strip debug $build_id_debug_relative" + return +} +set build_id_filename "${binmainfiledirrun}/$build_id_relative" +file mkdir [file dirname $build_id_filename] +remote_exec host "ln -sf $binmainfilerun-backup $build_id_filename" + +with_test_prefix "build-id autodetected executable" { + clean_restart + + gdb_test_no_output "set debug-file-directory $binmainfiledirrun" "set debug-file-directory" + + set test "attach" + gdb_test_multiple "attach $testpid" "$test" { + -re "\r\nwarning: Detected exec-file mismatch .*\r\n$gdb_prompt $" { + fail "$test" + } + -re "\r\nwarning: inferior build ID .*\r\n$gdb_prompt $" { + fail "$test" + } + -re "Attaching to process $testpid\r\n.*\r\n$gdb_prompt $" { + pass "$test" + } + } + + gdb_test "bt" " in main \[^\r\n\]*" + + gdb_test "detach" +} + +kill_wait_spawned_process $test_spawn_id