From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 20495 invoked by alias); 27 Feb 2013 17:31:51 -0000 Received: (qmail 20436 invoked by uid 22791); 27 Feb 2013 17:31:47 -0000 X-SWARE-Spam-Status: No, hits=-3.6 required=5.0 tests=AWL,BAYES_00,KHOP_THREADED,RCVD_IN_DNSWL_NONE,RP_MATCHES_RCVD,SPF_HELO_PASS,TW_BJ,TW_CP,TW_JC X-Spam-Check-By: sourceware.org Received: from plane.gmane.org (HELO plane.gmane.org) (80.91.229.3) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Wed, 27 Feb 2013 17:31:15 +0000 Received: from list by plane.gmane.org with local (Exim 4.69) (envelope-from ) id 1UAkqr-0007tb-LT for gdb-patches@sourceware.org; Wed, 27 Feb 2013 18:31:33 +0100 Received: from cpe0013d4b66ebb-cmbc1401279e60.cpe.net.cable.rogers.com ([99.224.111.207]) by main.gmane.org with esmtp (Gmexim 0.1 (Debian)) id 1AlnuQ-0007hv-00 for ; Wed, 27 Feb 2013 18:31:33 +0100 Received: from aristovski by cpe0013d4b66ebb-cmbc1401279e60.cpe.net.cable.rogers.com with local (Gmexim 0.1 (Debian)) id 1AlnuQ-0007hv-00 for ; Wed, 27 Feb 2013 18:31:33 +0100 To: gdb-patches@sourceware.org From: Aleksandar Ristovski Subject: Re: [patch] validate binary before use Date: Wed, 27 Feb 2013 18:14:00 -0000 Message-ID: <512E42D1.3040101@qnx.com> References: <50D4C49A.6040502@qnx.com> <50D8B37A.20001@qnx.com> <20121225073709.GA11349@host2.jankratochvil.net> <50DCAA5C.3000301@qnx.com> <20121227205924.GA5109@host2.jankratochvil.net> <50DCB787.6020601@qnx.com> <20121227211328.GA5739@host2.jankratochvil.net> <50DCBBD1.7000707@qnx.com> <5107F591.304@qnx.com> <20130131063518.GA3027@host2.jankratochvil.net> <510A7EB0.90702@qnx.com> <51278A2A.9000802@qnx.com> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="------------060805030102010105030306" Cc: Jan Kratochvil , "gdb-patches@sourceware.org" , Pedro Alves User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:17.0) Gecko/20130221 Thunderbird/17.0.3 In-Reply-To: <51278A2A.9000802@qnx.com> 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: 2013-02/txt/msg00695.txt.bz2 Message-ID: <20130227181400.STj8gQyc78H072PO1UOPUtQHzD8Pg8CHUuFZ0QAzp9k@z> This is a multi-part message in MIME format. --------------060805030102010105030306 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Content-length: 3723 On 13-02-22 10:09 AM, Aleksandar Ristovski wrote: > On 13-01-31 09:24 AM, Aleksandar Ristovski wrote: >> On 13-01-31 01:35 AM, Jan Kratochvil wrote: >>> >>> Therefore there should be new build_id field in struct so_list where >>> svr4_current_sos_via_xfer_libraries will put it from gdbserver. In >>> local mode >>> it should remain mostly as you wrote it / as suggested in the review >>> as there >>> is currently no easy non-Linux way how to find PT_NOTE without bfd at >>> hand. >>> >>> >> >> Ok, I can add this. Will be included in the new patch. >> >> > > > I have added build-id to gdbserver response. Patch is posted here: > http://sourceware.org/ml/gdb-patches/2013-02/msg00590.html > Here is new solib validate patch utilizing build-id returned from the gdbserver when available. This patch depends on: http://sourceware.org/ml/gdb-patches/2013-02/msg00692.html Thanks, Aleksandar ChangeLog followed by testsuite changelog: DATE Aleksandar Ristovski * Makefile.in (HFILES_NO_SRCDIR): Add linux-maps.h and linux-maps.c. * common/common-utils.c (TARGET_CHAR_BIT): Define if not defined. (HOST_CHAR_BIT): Ditto. (ctype.h): Include. (string.h): Include. (assert.h): Include. (HIGH_BYTE_POSN): Moved from utils.c. (is_digit_in_base): Ditto. (digit_to_int): Ditto. (strtoulst): Ditto. (fromhex): Moved from remote.c. (hex2bin): Ditto. (tohex): Ditto. (bin2hex): Ditto. * common/common-utils.h (strtoulst): Moved from utils.h. (tohex): New declaration. (fromhex): Ditto. (hex2bin): Ditto. (bin2hex): Ditto. * common/xml-utils.h (xml_hex_encode_text): Declare. * config/i386/linux.mk (NATDEPFILES): Add linux-maps.o. * config/i386/linux64.mh (NATDEPFILES): Add linux-maps.o. * features/library-list-svr4.dtd (build-id): New attribute. * gdbserver/Makefile.in (linux-maps.o): New. * gdbserver/configure.srv (srv_tgtobj): Add linux-maps.o. * gdbserver/linux-low.c (linux-maps.h): Include. (find_memory_region_callback_data): New structure definition. (find_memory_region_callback): New forward declaration. (find_memory_region_callback): New function. (get_hex_build_id): New function. (linux_qxfer_libraries_svr4): Add hex encoded build-id to the reply. * remote-utils.c (common-utils.h): Include. (fromhex): Moved to common-utils.c. (unhexify): Use hex2bin. (tohex): Moved to common-utils.c. (hexify): Use bin2hex. * linux-tdep.c (linux-maps.h): Include. (read_mapping): Moved to linux-maps.c. (linux_find_memory_region_ftype): Moved to linux-maps.h. (linux_find_memory_regions_full): Moved to linux-maps.c. (linux_find_memory_regions): Check for fake_pid_p to match functionality of original linux_find_memory_regions_full. (linux_make_mappings_corefile_notes): Ditto. * remote.c (tohex): Remove forward declaration. (fromhex): Ditto. (hex2bin): Ditto. (bin2hex): Ditto. (fromhex): Move implementation to common-utils.c (hex2bin): Ditto. (tohex): Ditto. (bin2hex): Ditto. * tracepoint.c (hex2bin): Remove declaration. (bin2hex): Ditto. * utils.c (HIGH_BYTE_POSN): Moved to common-utils.c. (is_digit_in_base): Ditto. (digit_to_int): Ditto. (strtoulst): Ditto. * utils.h (strtoulst): Moved to common-utils.h. testsuite/ChangeLog: * gdb.base/solib-mismatch-lib.c: New file. * gdb.base/solib-mismatch-libmod.c: Ditto. * * gdb.base/solib-mismatch.c: Ditto. * * gdb.base/solib-mismatch.exp: Ditto. --------------060805030102010105030306 Content-Type: text/x-patch; name="solib-validate-201302271227.patch" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="solib-validate-201302271227.patch" Content-length: 14748 diff --git a/gdb/common/common-utils.c b/gdb/common/common-utils.c index 780ba09..79d2b3e 100644 --- a/gdb/common/common-utils.c +++ b/gdb/common/common-utils.c @@ -295,6 +295,9 @@ hex2bin (const char *hex, gdb_byte *bin, size_t count) { size_t i; + if (count == 0) + count = (strlen (hex) + 1) / 2; + for (i = 0; i < count; i++) { int hi, lo; @@ -305,7 +308,6 @@ hex2bin (const char *hex, gdb_byte *bin, size_t count) { /* Hex string is short, or of uneven length or malformed. Return the count that has been converted so far. */ - warning (_("Malformed hex encoded string: '%s'\n"), hex); return i; } diff --git a/gdb/mips-linux-tdep.c b/gdb/mips-linux-tdep.c index 4589f19..96c9ece 100644 --- a/gdb/mips-linux-tdep.c +++ b/gdb/mips-linux-tdep.c @@ -1495,6 +1495,8 @@ mips_linux_init_abi (struct gdbarch_info info, mips_svr4_so_ops.in_dynsym_resolve_code = mips_linux_in_dynsym_resolve_code; } + if (mips_svr4_so_ops.validate == NULL) + mips_svr4_so_ops.validate = solib_validate; set_solib_ops (gdbarch, &mips_svr4_so_ops); set_gdbarch_write_pc (gdbarch, mips_linux_write_pc); diff --git a/gdb/ppc-linux-tdep.c b/gdb/ppc-linux-tdep.c index 0fc6fe0..92dc41a 100644 --- a/gdb/ppc-linux-tdep.c +++ b/gdb/ppc-linux-tdep.c @@ -1324,6 +1324,8 @@ ppc_linux_init_abi (struct gdbarch_info info, powerpc_so_ops.in_dynsym_resolve_code = powerpc_linux_in_dynsym_resolve_code; } + if (powerpc_so_ops.validate == NULL) + powerpc_so_ops.validate = solib_validate; set_solib_ops (gdbarch, &powerpc_so_ops); set_gdbarch_skip_solib_resolver (gdbarch, glibc_skip_solib_resolver); diff --git a/gdb/solib-darwin.c b/gdb/solib-darwin.c index 93212bd..cb0b941 100644 --- a/gdb/solib-darwin.c +++ b/gdb/solib-darwin.c @@ -647,4 +647,5 @@ _initialize_darwin_solib (void) darwin_so_ops.in_dynsym_resolve_code = darwin_in_dynsym_resolve_code; darwin_so_ops.lookup_lib_global_symbol = darwin_lookup_lib_symbol; darwin_so_ops.bfd_open = darwin_bfd_open; + darwin_so_ops.validate = solib_validate; } diff --git a/gdb/solib-dsbt.c b/gdb/solib-dsbt.c index c41326b..f7382ac 100644 --- a/gdb/solib-dsbt.c +++ b/gdb/solib-dsbt.c @@ -1182,6 +1182,7 @@ _initialize_dsbt_solib (void) dsbt_so_ops.open_symbol_file_object = open_symbol_file_object; dsbt_so_ops.in_dynsym_resolve_code = dsbt_in_dynsym_resolve_code; dsbt_so_ops.bfd_open = solib_bfd_open; + dsbt_so_ops.validate = solib_validate; /* Debug this file's internals. */ add_setshow_zuinteger_cmd ("solib-dsbt", class_maintenance, diff --git a/gdb/solib-frv.c b/gdb/solib-frv.c index 57e418f..e8de6ed 100644 --- a/gdb/solib-frv.c +++ b/gdb/solib-frv.c @@ -1182,6 +1182,7 @@ _initialize_frv_solib (void) frv_so_ops.open_symbol_file_object = open_symbol_file_object; frv_so_ops.in_dynsym_resolve_code = frv_in_dynsym_resolve_code; frv_so_ops.bfd_open = solib_bfd_open; + frv_so_ops.validate = solib_validate; /* Debug this file's internals. */ add_setshow_zuinteger_cmd ("solib-frv", class_maintenance, diff --git a/gdb/solib-ia64-hpux.c b/gdb/solib-ia64-hpux.c index 67085d7..b5d3b6b 100644 --- a/gdb/solib-ia64-hpux.c +++ b/gdb/solib-ia64-hpux.c @@ -686,6 +686,7 @@ ia64_hpux_target_so_ops (void) ops->open_symbol_file_object = ia64_hpux_open_symbol_file_object; ops->in_dynsym_resolve_code = ia64_hpux_in_dynsym_resolve_code; ops->bfd_open = solib_bfd_open; + ops->validate = solib_validate; return ops; } diff --git a/gdb/solib-irix.c b/gdb/solib-irix.c index af3e7d6..642e973 100644 --- a/gdb/solib-irix.c +++ b/gdb/solib-irix.c @@ -652,4 +652,5 @@ _initialize_irix_solib (void) irix_so_ops.open_symbol_file_object = irix_open_symbol_file_object; irix_so_ops.in_dynsym_resolve_code = irix_in_dynsym_resolve_code; irix_so_ops.bfd_open = solib_bfd_open; + irix_so_ops.validate = solib_validate; } diff --git a/gdb/solib-osf.c b/gdb/solib-osf.c index d05c5c1..f7298e3 100644 --- a/gdb/solib-osf.c +++ b/gdb/solib-osf.c @@ -633,6 +633,7 @@ _initialize_osf_solib (void) osf_so_ops.open_symbol_file_object = osf_open_symbol_file_object; osf_so_ops.in_dynsym_resolve_code = osf_in_dynsym_resolve_code; osf_so_ops.bfd_open = solib_bfd_open; + osf_so_ops.validate = solib_validate; /* FIXME: Don't do this here. *_gdbarch_init() should set so_ops. */ current_target_so_ops = &osf_so_ops; diff --git a/gdb/solib-pa64.c b/gdb/solib-pa64.c index eb27b40..101455a 100644 --- a/gdb/solib-pa64.c +++ b/gdb/solib-pa64.c @@ -623,6 +623,7 @@ _initialize_pa64_solib (void) pa64_so_ops.open_symbol_file_object = pa64_open_symbol_file_object; pa64_so_ops.in_dynsym_resolve_code = pa64_in_dynsym_resolve_code; pa64_so_ops.bfd_open = solib_bfd_open; + pa64_so_ops.validate = solib_validate; memset (&dld_cache, 0, sizeof (dld_cache)); } diff --git a/gdb/solib-som.c b/gdb/solib-som.c index bd763b8..e430e13 100644 --- a/gdb/solib-som.c +++ b/gdb/solib-som.c @@ -811,6 +811,7 @@ _initialize_som_solib (void) som_so_ops.open_symbol_file_object = som_open_symbol_file_object; som_so_ops.in_dynsym_resolve_code = som_in_dynsym_resolve_code; som_so_ops.bfd_open = solib_bfd_open; + som_so_ops.validate = solib_validate; } void diff --git a/gdb/solib-spu.c b/gdb/solib-spu.c index 6eb45a5..58ea391 100644 --- a/gdb/solib-spu.c +++ b/gdb/solib-spu.c @@ -519,6 +519,7 @@ set_spu_solib_ops (struct gdbarch *gdbarch) spu_so_ops.current_sos = spu_current_sos; spu_so_ops.bfd_open = spu_bfd_open; spu_so_ops.lookup_lib_global_symbol = spu_lookup_lib_symbol; + spu_so_ops.validate = solib_validate; } set_solib_ops (gdbarch, &spu_so_ops); diff --git a/gdb/solib-sunos.c b/gdb/solib-sunos.c index 5863fc2..fec2e9a 100644 --- a/gdb/solib-sunos.c +++ b/gdb/solib-sunos.c @@ -738,6 +738,7 @@ _initialize_sunos_solib (void) sunos_so_ops.open_symbol_file_object = open_symbol_file_object; sunos_so_ops.in_dynsym_resolve_code = sunos_in_dynsym_resolve_code; sunos_so_ops.bfd_open = solib_bfd_open; + sunos_so_ops.validate = solib_validate; /* FIXME: Don't do this here. *_gdbarch_init() should set so_ops. */ current_target_so_ops = &sunos_so_ops; diff --git a/gdb/solib-svr4.c b/gdb/solib-svr4.c index 0f70097..34525dd 100644 --- a/gdb/solib-svr4.c +++ b/gdb/solib-svr4.c @@ -189,7 +189,7 @@ has_lm_dynamic_from_link_map (void) } static CORE_ADDR -lm_addr_check (struct so_list *so, bfd *abfd) +lm_addr_check (const struct so_list *so, bfd *abfd) { if (!so->lm_info->l_addr_p) { @@ -871,6 +871,87 @@ svr4_keep_data_in_core (CORE_ADDR vaddr, unsigned long size) return (name_lm >= vaddr && name_lm < vaddr + size); } + +/* If build-id exists, compare it with target in-memory contents. + Return 1 if they match, 0 if they don't. + If there was no build-id, return 1 (could not be verified). */ + +static int +svr4_validate_build_id (const struct so_list *const so) +{ + asection *asect; + int res = 1; + size_t size; + const CORE_ADDR l_addr = lm_addr_check (so, so->abfd); + + if (!bfd_check_format (so->abfd, bfd_object) + || bfd_get_flavour (so->abfd) != bfd_target_elf_flavour + || elf_tdata (so->abfd)->build_id == NULL) + return 1; + + asect = bfd_get_section_by_name (so->abfd, NOTE_GNU_BUILD_ID_NAME); + + if (!asect || !so->lm_info->l_addr_p) + { + if (info_verbose) + warning (_("Could not verify '%s' section.\n"), + NOTE_GNU_BUILD_ID_NAME); + return 1; + } + + size = bfd_get_section_size (asect); + + if ((asect->flags & SEC_LOAD) == SEC_LOAD && size != 0) + { + gdb_byte *build_id = so->build_id; + size_t build_idsz = so->build_idsz; + gdb_byte *const data = xmalloc (size); + struct cleanup *const cleanups = make_cleanup (xfree, data); + /* Zero based vma, after undoing link script non zero base + and/or prelinked rebasing. */ + const CORE_ADDR sect_lma = l_addr + bfd_section_vma (so->abfd, asect); + + /* Relocated or not, contents will be corectly loaded from + the file by bfd library. */ + bfd_get_section_contents ((bfd *) so->abfd, asect, data, 0, size); + + if (build_id == NULL) + { + build_idsz = size; + build_id = xmalloc (size); + make_cleanup (xfree, build_id); + if (target_read_memory (sect_lma, build_id, size) != 0) + { + build_id = NULL; + res = -1; + } + } + + if (build_id != NULL) + res = size == build_idsz + && memcmp (build_id, data, size) == 0; + + if (res == -1 && info_verbose) + warning (_("Could not verify section %s\n"), NOTE_GNU_BUILD_ID_NAME); + + do_cleanups (cleanups); + } + + return res != 0; +} + +/* Validate SO by checking whether opened file matches + in-memory object. */ + +static int +svr4_validate (const struct so_list *const so) +{ + gdb_assert (so != NULL); + gdb_assert (so->abfd != NULL); + + return svr4_validate_build_id (so); +} + /* Implement the "open_symbol_file_object" target_so_ops method. If no open symbol file, attempt to locate and open the main symbol @@ -999,6 +1080,9 @@ library_list_start_library (struct gdb_xml_parser *parser, ULONGEST *lmp = xml_find_attribute (attributes, "lm")->value; ULONGEST *l_addrp = xml_find_attribute (attributes, "l_addr")->value; ULONGEST *l_ldp = xml_find_attribute (attributes, "l_ld")->value; + const struct gdb_xml_value *const att_build_id + = xml_find_attribute (attributes, "build-id"); + const char *const hex_build_id = att_build_id ? att_build_id->value : NULL; struct so_list *new_elem; new_elem = XZALLOC (struct so_list); @@ -1010,6 +1094,20 @@ library_list_start_library (struct gdb_xml_parser *parser, strncpy (new_elem->so_name, name, sizeof (new_elem->so_name) - 1); new_elem->so_name[sizeof (new_elem->so_name) - 1] = 0; strcpy (new_elem->so_original_name, new_elem->so_name); + if (hex_build_id != NULL && strlen (hex_build_id) > 0) + { + new_elem->build_id = xmalloc (strlen (hex_build_id) / 2 + 1); + new_elem->build_idsz = hex2bin (hex_build_id, new_elem->build_id, 0); + if (new_elem->build_idsz != (strlen (hex_build_id) / 2)) + { + warning (_("Gdbserver returned invalid hex encoded build_id '%s'" + "(%zu/%zu)\n"), + hex_build_id, strlen (hex_build_id), new_elem->build_idsz); + xfree (new_elem->build_id); + new_elem->build_id = NULL; + new_elem->build_idsz = 0; + } + } *list->tailp = new_elem; list->tailp = &new_elem->next; @@ -1044,6 +1142,7 @@ static const struct gdb_xml_attribute svr4_library_attributes[] = { "lm", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL }, { "l_addr", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL }, { "l_ld", GDB_XML_AF_NONE, gdb_xml_parse_attr_ulongest, NULL }, + { "build-id", GDB_XML_AF_NONE, NULL, NULL }, { NULL, GDB_XML_AF_NONE, NULL, NULL } }; @@ -2458,4 +2557,5 @@ _initialize_svr4_solib (void) svr4_so_ops.lookup_lib_global_symbol = elf_lookup_lib_symbol; svr4_so_ops.same = svr4_same; svr4_so_ops.keep_data_in_core = svr4_keep_data_in_core; + svr4_so_ops.validate = svr4_validate; } diff --git a/gdb/solib-svr4.h b/gdb/solib-svr4.h index 66a06e1..ba17dbe 100644 --- a/gdb/solib-svr4.h +++ b/gdb/solib-svr4.h @@ -20,6 +20,9 @@ #ifndef SOLIB_SVR4_H #define SOLIB_SVR4_H +#define DYNAMIC_NAME ".dynamic" +#define NOTE_GNU_BUILD_ID_NAME ".note.gnu.build-id" + struct objfile; struct target_so_ops; diff --git a/gdb/solib-target.c b/gdb/solib-target.c index d897bc0..f43037a 100644 --- a/gdb/solib-target.c +++ b/gdb/solib-target.c @@ -25,6 +25,7 @@ #include "target.h" #include "vec.h" #include "solib-target.h" +#include "solib.h" #include "gdb_string.h" @@ -500,6 +501,7 @@ _initialize_solib_target (void) solib_target_so_ops.in_dynsym_resolve_code = solib_target_in_dynsym_resolve_code; solib_target_so_ops.bfd_open = solib_bfd_open; + solib_target_so_ops.validate = solib_validate; /* Set current_target_so_ops to solib_target_so_ops if not already set. */ diff --git a/gdb/solib.c b/gdb/solib.c index 8129c0f..0d68373 100644 --- a/gdb/solib.c +++ b/gdb/solib.c @@ -477,6 +477,17 @@ solib_map_sections (struct so_list *so) bfd_get_filename (abfd), bfd_errmsg (bfd_get_error ())); } + gdb_assert (ops->validate != NULL); + + if (!ops->validate (so)) + { + warning (_("Shared object \"%s\" could not be validated and will be ignored."), + so->so_name); + gdb_bfd_unref (so->abfd); + so->abfd = NULL; + return 0; + } + for (p = so->sections; p < so->sections_end; p++) { /* Relocate the section binding addresses as recorded in the shared @@ -551,6 +562,7 @@ free_so (struct so_list *so) { struct target_so_ops *ops = solib_ops (target_gdbarch ()); + xfree (so->build_id); free_so_symbols (so); ops->free_so (so); @@ -1448,6 +1460,14 @@ gdb_bfd_lookup_symbol (bfd *abfd, return symaddr; } +/* Default implementation does not perform any validation. */ + +int +solib_validate (const struct so_list *const so) +{ + return 1; /* No validation. */ +} + extern initialize_file_ftype _initialize_solib; /* -Wmissing-prototypes */ void diff --git a/gdb/solib.h b/gdb/solib.h index b811866..ae42e9d 100644 --- a/gdb/solib.h +++ b/gdb/solib.h @@ -90,4 +90,8 @@ extern CORE_ADDR gdb_bfd_lookup_symbol_from_symtab (bfd *abfd, void *), void *data); +/* Default validation always returns 1. */ + +extern int solib_validate (const struct so_list *so); + #endif /* SOLIB_H */ diff --git a/gdb/solist.h b/gdb/solist.h index f784fc3..5eaa442 100644 --- a/gdb/solist.h +++ b/gdb/solist.h @@ -75,6 +75,14 @@ struct so_list There may not be just one (e.g. if two segments are relocated differently); but this is only used for "info sharedlibrary". */ CORE_ADDR addr_low, addr_high; + + /* Build id in raw format. This is actual BUILD_ID which comes + either from the remote target via qXfer packet or via + reading target memory. Therefore, it may differ from the + actual build-id from the associated bfd. In a normal scenario, + this so would soon lose its abfd due to failed validation. */ + size_t build_idsz; + gdb_byte *build_id; }; struct target_so_ops @@ -148,6 +156,10 @@ struct target_so_ops core file (in particular, for readonly sections). */ int (*keep_data_in_core) (CORE_ADDR vaddr, unsigned long size); + + /* Return 0 if SO does not match target SO it is supposed to + represent. Return 1 otherwise. */ + int (*validate) (const struct so_list *so); }; /* Free the memory associated with a (so_list *). */ -- 1.7.10.4 --------------060805030102010105030306 Content-Type: text/x-patch; name="solib-validate-test-201302271228.patch" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="solib-validate-test-201302271228.patch" Content-length: 9976 diff --git a/gdb/testsuite/gdb.base/solib-mismatch-lib.c b/gdb/testsuite/gdb.base/solib-mismatch-lib.c new file mode 100644 index 0000000..19f1545 --- /dev/null +++ b/gdb/testsuite/gdb.base/solib-mismatch-lib.c @@ -0,0 +1,29 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2013 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 . */ + + +int _bar = 42; + +int bar(void) +{ + return _bar + 21; +} + +int foo(void) +{ + return _bar; +} diff --git a/gdb/testsuite/gdb.base/solib-mismatch-libmod.c b/gdb/testsuite/gdb.base/solib-mismatch-libmod.c new file mode 100644 index 0000000..3b025a8 --- /dev/null +++ b/gdb/testsuite/gdb.base/solib-mismatch-libmod.c @@ -0,0 +1,29 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2013 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 . */ + + +int _bar = 21; + +int bar(void) +{ + return 42 - _bar; +} + +int foo(void) +{ + return 24 + bar(); +} diff --git a/gdb/testsuite/gdb.base/solib-mismatch.c b/gdb/testsuite/gdb.base/solib-mismatch.c new file mode 100644 index 0000000..85a2784 --- /dev/null +++ b/gdb/testsuite/gdb.base/solib-mismatch.c @@ -0,0 +1,59 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2013 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 +#include +#include +#include + +#define lib "./solib-mismatch.so" + + +/* First argument is working directory. */ + +int main(int argc, char *argv[]) +{ + void *h; + int (*foo)(void); + char buff[1024]; + + if (argc < 2) + { + printf ("ERROR - CWD not provided\n"); + return 1; + } + + if (chdir (argv[1]) != 0) + { + printf ("ERROR - Could not cd to '%s'\n", argv[1]); + return 1; + } + + h = dlopen(lib, RTLD_NOW); + + if (h == NULL) + { + printf ("ERROR - could not open lib %s\n", lib); + return 1; + } + foo = dlsym(h, "foo"); + printf ("foo: %p\n", foo); /* set breakpoint 1 here */ + dlclose(h); + return 0; +} + diff --git a/gdb/testsuite/gdb.base/solib-mismatch.exp b/gdb/testsuite/gdb.base/solib-mismatch.exp new file mode 100644 index 0000000..c2192a5 --- /dev/null +++ b/gdb/testsuite/gdb.base/solib-mismatch.exp @@ -0,0 +1,186 @@ +# Copyright 2013 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 . */ + +# are we on a target board +standard_testfile +set executable $testfile + +# Test overview: +# generate two shared objects. 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 shared object. + +if { [get_compiler_info] } { + untested ${testfile}.exp +} + +# First version of the object, to be loaded by ld +set srclibfilerun ${testfile}-lib.c +# Modified version of the object to be loaded by gdb +# Code in -libmod.c is tuned so it gives a mismatch but +# leaves .dynamic at the same point. +set srclibfilegdb ${testfile}-libmod.c + +# So file name: +set binlibfilebase ${testfile}.so + +# Setup run directory (where program is run from) +# It contains executable and '-lib' version of the library. +set binlibfiledirrun ${objdir}/${subdir}/${testfile}_wd +set binlibfilerun ${binlibfiledirrun}/${binlibfilebase} + +# Second solib version is in current directory, '-libmod' version. +set binlibfiledirgdb ${objdir}/${subdir} +set binlibfilegdb ${binlibfiledirgdb}/${binlibfilebase} + +# Executeable +set srcfile ${testfile}.c +set executable ${testfile} +set objfile ${objdir}/${subdir}/${executable}.o +set binfile ${objdir}/${subdir}/${executable} + +send_user "Current WD: [eval pwd]\r\n" + +file mkdir "${binlibfiledirrun}" + +if { ![istarget "*-*-nto-*"] } { + set exec_opts [list debug shlib_load] +} + +if { [prepare_for_testing $testfile.exp $executable $srcfile $exec_opts] != 0 } { + untested ${testfile}.exp + return -1 +} + +if { [gdb_compile_shlib "${srcdir}/${subdir}/${srclibfilerun}" "${binlibfilerun}" [list debug ldflags=-Wl,-soname,${binlibfilebase},--build-id]] != "" + || [gdb_gnu_strip_debug "${binlibfilerun}"] + || [gdb_compile_shlib "${srcdir}/${subdir}/${srclibfilegdb}" "${binlibfilegdb}" [list debug ldflags=-Wl,-soname,${binlibfilebase},--build-id]] != "" } { + untested ${testfile}.exp + return -1 +} + +proc solib_matching_test { solibfile symsloaded } { + global gdb_prompt + global testfile + global executable + global srcdir + global subdir + global binlibfiledirrun + global binlibfiledirgdb + global srcfile + + gdb_exit + gdb_start + gdb_reinitialize_dir $srcdir/$subdir + + send_gdb "set verbose 1\n" + send_gdb "file \"${binlibfiledirrun}/${executable}\"\n" + send_gdb "set solib-search-path \"${binlibfiledirgdb}\"\n" + send_gdb "cd ${binlibfiledirgdb}\n" + send_gdb "show solib-search-path\n" + send_gdb "set auto-solib-add off\n" + send_gdb "set args \"${binlibfiledirrun}\"\n" + send_gdb "set verbose 1\n" + + set bp_location [gdb_get_line_number "set breakpoint 1 here"] + + send_gdb "tbreak ${srcfile}:${bp_location}\n" + gdb_expect { + -re ".*Temporary breakpoint.*${gdb_prompt} $" { + } + default { + untested "${testfile}: Failed to set temp. breakpoint at ${bp_location}" + return -1 + } + } + + send_gdb "run\r\n" + gdb_expect { + -re "Starting program.*${gdb_prompt} $" { + } + default { + untested "${testfile}: Failed to hit breakpoint at ${bp_location}" + return -1 + } + } + + send_gdb "sharedlibrary\n" + gdb_expect { + -re ".*${gdb_prompt} $" { + } + default { + untested "${testfile}: sharedlibrary failure" + return -1 + } + } + + gdb_test "info sharedlibrary ${solibfile}" \ + ".*From.*To.*Syms.*Read.*Shared.*\r\n.*${symsloaded}.*" \ + "Symbols for ${solibfile} loaded: expected '${symsloaded}'" + + send_gdb "p/x foo\n" + gdb_expect { + -re ".*${gdb_prompt} $" { +#Nothing, just drain the buffer + } + default { + untested "${testfile}: Failed 'info symbol foo'" + return -1 + } + } + + send_gdb "detach\n" + gdb_expect { + -re ".*Detaching from program.*${executable}.*${gdb_prompt} $" { +#Nothing, just drain the buffer + } + default { + untested "${testfile}: Could not detach from ${testpid}" + return -1 + } + } + return 0 +} + +# Copy binary to working dir so it pulls in the library from that dir +# (by the virtue of $ORIGIN). +file copy -force "${binlibfiledirgdb}/${executable}" \ + "${binlibfiledirrun}/${executable}" + +# Test unstripped, .dynamic matching +send_user "test unstripped, .dynamic matching\r\n" +solib_matching_test "${binlibfilebase}" "No" + +# Test --only-keep-debug, .dynamic matching so +send_user "test --only-keep-debug\r\n" +# Keep original so for debugging purposes +file copy -force "${binlibfilegdb}" "${binlibfilegdb}-orig" +set objcopy_program [transform objcopy] +set result [catch "exec $objcopy_program --only-keep-debug ${binlibfilegdb}"] +if {$result != 0} { + untested "${testfile} test --only-keep-debug" + return -1 +} +solib_matching_test "${binlibfilebase}" "No" + +# Now test it does not mis-invalidate matching libraries +send_user "test matching libraries\r\n" +# Keep previous so for debugging puroses +file copy -force "${binlibfilegdb}" "${binlibfilegdb}-orig1" +# Copy loaded so over the one gdb will find +file copy -force "${binlibfilerun}" "${binlibfilegdb}" +solib_matching_test "${binlibfilebase}" "Yes" + + -- 1.7.10.4 --------------060805030102010105030306--