This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [patch] validate binary before use


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 <aristovski@qnx.com>


* 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.

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

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 <http://www.gnu.org/licenses/>.  */
+
+
+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 <http://www.gnu.org/licenses/>.  */
+
+
+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 <http://www.gnu.org/licenses/>.  */
+
+
+#include <dlfcn.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <signal.h>
+
+#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 <http://www.gnu.org/licenses/>.  */
+
+# 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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]