[patch] validate binary before use

Aleksandar Ristovski
2012-12-21T20:21:06Z

[-- Attachment #1: Type: text/plain, Size: 2792 bytes --]

Hello all,

Currently gdb may use mismatched binary without complaining or noticing.
This is particularly often the case when debugging remote targets, or
multiple of, with multiple versions of libraries.

The situation is possible on self hosted as well.

For example, consider having:
1) a library called 'libso.so.1', with SONAME 'libso.so.1';
2) a program linked against it;
3) environment in which program can be executed and library from 1)
found by the dynamic linker;
4) modified libso.so.1, different from the one found by the dynamic
linker in 3), in the current working directory of gdb;
5) attach to process stared in 3) using gdb.

What happens is, gdb will happily use modified libso.so.1 from current
working directory without noticing the mismatch. This causes a lot of
confusion.

(I can elaborate on the example if needed).

Change introduces new target_so_ops function dedicated to performing
validation. If we have loaded and relocated the object, validation
fails, we throw away bfd and loading of the object fails.

The gist of the change is in solib-svr4.c and solib.c The rest are
mechanical changes to fill-in new field with valid value.

(for bonus points, solib-svr4.c now compiles without -Wno-unused)

Regression test suite shows no regressions. (tested on
x86_64-unknown-linux-gnu).

Thanks,

Aleksandar

ChangeLog:

<date> Aleksandar Ristovski <aristovski@qnx.com>

* solib-svr4.c (read_program_headers_from_bfd,
read_elf_header_from_bfd): Forward declare.
(svr4_keep_data_in_core): Remove unused variable.
(read_elf_header_from_target, read_program_headers_from_target,
svr4_validate_hdrs_match, svr4_validate): New function.
(svr4_read_so_list): Remove unused variable.
(read_elf_header_from_bfd): New function.
(_initialize_svr4_solib): Use svr4_validate.
* solib.c (solib_map_sections): Validate loaded SO.
(solib_validate): New function.
* solib.h (solib_validate): Declare.
* solist.h (target_so_ops): New field 'validate'.
* mips-linux-tdep.c (mips_linux_init_abi): Assign validate value.
* ppc-linux-tdep.c (ppc_linux_init_abi): Ditto.
* solib-darwin.c (_initialize_darwin_solib): Ditto.
* solib-dsbt.c (_initialize_dsbt_solib): Ditto.
* solib-frv.c (_initialize_frv_solib): Ditto.
* solib-ia64-hpux.c (ia64_hpux_target_so_ops): Ditto.
* solib-irix.c (_initialize_irix_solib): Ditto.
* solib-osf.c (_initialize_osf_solib): Ditto.
* solib-pa64.c (_initialize_pa64_solib): Ditto.
* solib-som.c (_initialize_som_solib): Ditto.
* solib-spu.c (set_spu_solib_ops): Ditto.
* solib-sunos.c (_initialize_sunos_solib): Ditto.
* solib-target.c (solib.h): Include.
(_initialize_solib_target): Assign validate value.

[-- Attachment #2: solib-validate-201212211440.patch --]
[-- Type: text/x-patch, Size: 19493 bytes --]

Index: gdb/solib-svr4.c
===================================================================
RCS file: /cvs/src/src/gdb/solib-svr4.c,v
retrieving revision 1.171
diff -u -p -r1.171 solib-svr4.c
--- gdb/solib-svr4.c 13 Dec 2012 21:29:50 -0000 1.171
+++ gdb/solib-svr4.c 21 Dec 2012 19:40:44 -0000
@@ -51,6 +51,8 @@
static struct link_map_offsets *svr4_fetch_link_map_offsets (void);
static int svr4_have_link_map_offsets (void);
static void svr4_relocate_main_executable (void);
+static gdb_byte *read_program_headers_from_bfd (bfd *abfd, int *phdrs_size);
+static gdb_byte *read_elf_header_from_bfd (bfd *abfd, int *bfd_ehdr_size);

/* Link map info to include in an allocated so_list entry. */

@@ -849,7 +851,6 @@ svr4_keep_data_in_core (CORE_ADDR vaddr,
CORE_ADDR ldsomap;
struct so_list *new;
struct cleanup *old_chain;
- struct link_map_offsets *lmo;
CORE_ADDR name_lm;

info = get_svr4_info ();
@@ -863,7 +864,6 @@ svr4_keep_data_in_core (CORE_ADDR vaddr,
if (!ldsomap)
return 0;

- lmo = svr4_fetch_link_map_offsets ();
new = XZALLOC (struct so_list);
old_chain = make_cleanup (xfree, new);
new->lm_info = lm_info_read (ldsomap);
@@ -874,6 +874,201 @@ svr4_keep_data_in_core (CORE_ADDR vaddr,
return (name_lm >= vaddr && name_lm < vaddr + size);
}

+
+/* Read elf header corresponding to SO from target memory.
+ Allocates memory for the returned value (which ought be
+ freed with xfree). Returns elf header size in *HDR_SIZE. */
+
+static gdb_byte *
+read_elf_header_from_target (const struct so_list *const so,
+ int *const hdr_size)
+{
+ const CORE_ADDR so_base_addr = so->lm_info->l_addr;
+ const int ptr_size
+ = builtin_type (target_gdbarch ())->builtin_data_ptr->length;
+ const gdb_byte elf_magic[] = { 0x7f, 'E', 'L', 'F' };
+ int status;
+ gdb_byte *ret;
+
+ if (!so->lm_info->l_addr_p)
+ {
+ warning (_("Unable to load elf header from target since shared object %s has not been relocated."), so->abfd->filename);
+ return NULL;
+ }
+
+ *hdr_size = (ptr_size == 4)? sizeof (Elf32_External_Ehdr)
+ : sizeof (Elf64_External_Ehdr);
+
+ ret = xzalloc (*hdr_size);
+
+ if (ret == NULL)
+ {
+ warning (_("Unable to load elf header from target due to out of memory."));
+ return NULL;
+ }
+
+ if ((status = target_read_memory (so_base_addr, ret, *hdr_size)) != 0)
+ {
+ warning (_("Unable to load elf header from target due to failed memory read at address %s"),
+ paddress (target_gdbarch (), so_base_addr));
+ xfree (ret);
+ return NULL;
+ }
+
+ /* Verify that we have actually read the header. */
+ if (memcmp (elf_magic, ret, 4) != 0)
+ {
+ warning (_("Unable to load elf header from target due to elf magic string mismatch."));
+ xfree (ret);
+ return NULL;
+ }
+
+ return ret;
+}
+
+
+/* Read program headers from target memory for a given shared object.
+ SO must have been relocated and its addr_low correctly set. */
+
+static gdb_byte *
+read_program_headers_from_target (const struct so_list *const so,
+ int *const phdrs_size)
+{
+ const CORE_ADDR so_base_addr = so->lm_info->l_addr;
+ const enum bfd_endian byte_order = gdbarch_byte_order (target_gdbarch ());
+ const int ptr_size
+ = builtin_type (target_gdbarch ())->builtin_data_ptr->length;
+ union ElfXX_Ehdr
+ {
+ Elf32_External_Ehdr _32;
+ Elf64_External_Ehdr _64;
+ } ELF_EHDR;
+ unsigned phnum, phentsize, phoff; /* In our byte order */
+ int ehdr_size;
+ int status;
+ gdb_byte *e_phnum, *e_phentsize, *e_phoff;
+ int e_phnum_len, e_phentsize_len, e_phoff_len;
+ gdb_byte *ret;
+
+ if (!so->lm_info->l_addr_p)
+ {
+ warning (_("Unable to load program headers from target since shared object %s has not been relocated."), so->abfd->filename);
+ return NULL;
+ }
+
+ ret = read_elf_header_from_target (so, &ehdr_size);
+
+ if (ret == NULL)
+ return NULL;
+
+ memcpy (&ELF_EHDR, ret, ehdr_size);
+ xfree (ret);
+
+ if (ptr_size == 4)
+ {
+ e_phnum = (gdb_byte *) &ELF_EHDR._32.e_phnum;
+ e_phnum_len = sizeof (ELF_EHDR._32.e_phnum);
+ e_phentsize = (gdb_byte *) &ELF_EHDR._32.e_phentsize;
+ e_phentsize_len = sizeof (ELF_EHDR._32.e_phentsize);
+ e_phoff = (gdb_byte *) &ELF_EHDR._32.e_phoff;
+ e_phoff_len = sizeof (ELF_EHDR._32.e_phoff);
+ }
+ else
+ {
+ e_phnum = (gdb_byte *) &ELF_EHDR._64.e_phnum;
+ e_phnum_len = sizeof (ELF_EHDR._64.e_phnum);
+ e_phentsize = (gdb_byte *) &ELF_EHDR._64.e_phentsize;
+ e_phentsize_len = sizeof (ELF_EHDR._64.e_phentsize);
+ e_phoff = (gdb_byte *) &ELF_EHDR._64.e_phoff;
+ e_phoff_len = sizeof (ELF_EHDR._64.e_phoff);
+ }
+
+ phnum = extract_unsigned_integer (e_phnum, e_phnum_len, byte_order);
+ phentsize = extract_unsigned_integer (e_phentsize, e_phentsize_len,
+ byte_order);
+ phoff = extract_unsigned_integer (e_phoff, e_phoff_len, byte_order);
+
+ *phdrs_size = phnum * phentsize;
+
+ ret = xzalloc (*phdrs_size);
+ if (ret == NULL)
+ {
+ warning (_("Unable to load target pheaders due to out of memory."));
+ return NULL;
+ }
+
+ if ((status = target_read_memory (so_base_addr + phoff, ret, *phdrs_size))
+ != 0)
+ {
+ memory_error (status, so_base_addr + phoff);
+ xfree (ret);
+ return NULL;
+ }
+
+ return ret;
+}
+
+/* Validate elf header and phdrs of SO->ABFD and in-memory match. */
+
+static int
+svr4_validate_hdrs_match (const struct so_list *const so)
+{
+ int mem_ehdr_size, bfd_ehdr_size;
+ int mem_phdrs_size, bfd_phdrs_size;
+ gdb_byte *mem_ehdr, *mem_phdrs = NULL;
+ gdb_byte *bfd_ehdr = NULL, *bfd_phdrs = NULL;
+ int ok = 1;
+
+ mem_ehdr = read_elf_header_from_target (so, &mem_ehdr_size);
+ if (mem_ehdr)
+ mem_phdrs = read_program_headers_from_target (so, &mem_phdrs_size);
+ if (mem_phdrs)
+ bfd_ehdr = read_elf_header_from_bfd (so->abfd, &bfd_ehdr_size);
+ if (bfd_ehdr)
+ bfd_phdrs = read_program_headers_from_bfd (so->abfd, &bfd_phdrs_size);
+
+ if (bfd_phdrs != NULL)
+ {
+ /* Finally, check. Since both memory and file representations
+ must match, it is o.k. to bit compare headers. */
+ if (bfd_ehdr_size != mem_ehdr_size
+ || memcmp (mem_ehdr, bfd_ehdr, mem_ehdr_size) != 0)
+ {
+ warning (_("Elf header does not match for %s"),
+ so->abfd->filename);
+ ok = 0;
+ }
+ else if (bfd_phdrs_size != mem_phdrs_size
+ || memcmp (mem_phdrs, bfd_phdrs, mem_phdrs_size) != 0)
+ {
+ warning (_("Program headers do not match for %s"),
+ so->abfd->filename);
+ ok = 0;
+ }
+ }
+ else
+ warning (_("Unable to validate binary match for %s"), so->abfd->filename);
+
+ xfree (bfd_phdrs);
+ xfree (bfd_ehdr);
+ xfree (mem_phdrs);
+ xfree (mem_ehdr);
+
+ return ok;
+}
+
+/* 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_hdrs_match (so);
+}
+
/* Implement the "open_symbol_file_object" target_so_ops method.

If no open symbol file, attempt to locate and open the main symbol
@@ -1176,7 +1371,6 @@ svr4_read_so_list (CORE_ADDR lm, struct

for (; lm != 0; prev_lm = lm, lm = next_lm)
{
- struct link_map_offsets *lmo = svr4_fetch_link_map_offsets ();
struct so_list *new;
struct cleanup *old_chain;
int errcode;
@@ -1741,6 +1935,36 @@ svr4_special_symbol_handling (void)
/* Nothing to do. */
}

+/* Read the ELF header from ABFD. Return the raw contents and
+ set *ELFHDR_SIZE to the size of the elf header. */
+
+static gdb_byte *
+read_elf_header_from_bfd (bfd *const abfd, int *const bfd_ehdr_size)
+{
+ const int ptr_size
+ = builtin_type (target_gdbarch ())->builtin_data_ptr->length;
+ const int ehdr_size = (ptr_size == 4)? sizeof (Elf32_External_Ehdr)
+ : sizeof (Elf64_External_Ehdr);
+ gdb_byte *const bfd_ehdr = xmalloc (ehdr_size);
+
+ if (bfd_ehdr == NULL)
+ {
+ warning (_("Unable to read raw elf header due to out of memory."));
+ return NULL;
+ }
+
+ *bfd_ehdr_size = ehdr_size;
+
+ if (bfd_seek (abfd, 0, SEEK_SET) != 0
+ || bfd_bread (bfd_ehdr, ehdr_size, abfd) != ehdr_size)
+ {
+ warning (_("Unable to read raw elf header due to failed file operation."));
+ xfree (bfd_ehdr);
+ return NULL;
+ }
+ return bfd_ehdr;
+}
+
/* Read the ELF program headers from ABFD. Return the contents and
set *PHDRS_SIZE to the size of the program headers. */

@@ -2462,4 +2686,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;
}
Index: gdb/solib.c
===================================================================
RCS file: /cvs/src/src/gdb/solib.c,v
retrieving revision 1.168
diff -u -p -r1.168 solib.c
--- gdb/solib.c 9 Nov 2012 19:58:01 -0000 1.168
+++ gdb/solib.c 21 Dec 2012 19:40:47 -0000
@@ -495,6 +495,15 @@ solib_map_sections (struct so_list *so)
}
}

+ if (!ops->validate (so))
+ {
+ warning (_("Shared object could not be validated and will be ignored: %s."),
+ so->abfd->filename);
+ gdb_bfd_unref (so->abfd);
+ so->abfd = NULL;
+ return 0;
+ }
+
/* Add the shared object's sections to the current set of file
section tables. Do this immediately after mapping the object so
that later nodes in the list can query this object, as is needed
@@ -1448,6 +1457,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
Index: gdb/solib.h
===================================================================
RCS file: /cvs/src/src/gdb/solib.h,v
retrieving revision 1.33
diff -u -p -r1.33 solib.h
--- gdb/solib.h 3 Feb 2012 15:19:37 -0000 1.33
+++ gdb/solib.h 21 Dec 2012 19:40:49 -0000
@@ -91,4 +91,8 @@ extern CORE_ADDR gdb_bfd_lookup_symbol_f
void *),
void *data);

+/* Default validation always returns 1. */
+
+extern int solib_validate (const struct so_list *so);
+
#endif /* SOLIB_H */
Index: gdb/solist.h
===================================================================
RCS file: /cvs/src/src/gdb/solist.h,v
retrieving revision 1.37
diff -u -p -r1.37 solist.h
--- gdb/solist.h 4 Jan 2012 08:17:11 -0000 1.37
+++ gdb/solist.h 21 Dec 2012 19:40:51 -0000
@@ -149,6 +149,11 @@ 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 *). */
Index: gdb/mips-linux-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/mips-linux-tdep.c,v
retrieving revision 1.96
diff -u -p -r1.96 mips-linux-tdep.c
--- gdb/mips-linux-tdep.c 9 Nov 2012 19:57:59 -0000 1.96
+++ gdb/mips-linux-tdep.c 21 Dec 2012 19:40:53 -0000
@@ -1495,6 +1495,8 @@ mips_linux_init_abi (struct gdbarch_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);
Index: gdb/ppc-linux-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/ppc-linux-tdep.c,v
retrieving revision 1.140
diff -u -p -r1.140 ppc-linux-tdep.c
--- gdb/ppc-linux-tdep.c 8 Nov 2012 14:16:33 -0000 1.140
+++ gdb/ppc-linux-tdep.c 21 Dec 2012 19:40:55 -0000
@@ -1733,6 +1733,8 @@ ppc_linux_init_abi (struct gdbarch_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);
Index: gdb/solib-darwin.c
===================================================================
RCS file: /cvs/src/src/gdb/solib-darwin.c,v
retrieving revision 1.34
diff -u -p -r1.34 solib-darwin.c
--- gdb/solib-darwin.c 18 Dec 2012 06:19:54 -0000 1.34
+++ gdb/solib-darwin.c 21 Dec 2012 19:40:58 -0000
@@ -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;
}
Index: gdb/solib-dsbt.c
===================================================================
RCS file: /cvs/src/src/gdb/solib-dsbt.c,v
retrieving revision 1.8
diff -u -p -r1.8 solib-dsbt.c
--- gdb/solib-dsbt.c 9 Nov 2012 19:58:00 -0000 1.8
+++ gdb/solib-dsbt.c 21 Dec 2012 19:41:00 -0000
@@ -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,
Index: gdb/solib-frv.c
===================================================================
RCS file: /cvs/src/src/gdb/solib-frv.c,v
retrieving revision 1.48
diff -u -p -r1.48 solib-frv.c
--- gdb/solib-frv.c 9 Nov 2012 19:58:00 -0000 1.48
+++ gdb/solib-frv.c 21 Dec 2012 19:41:02 -0000
@@ -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,
Index: gdb/solib-ia64-hpux.c
===================================================================
RCS file: /cvs/src/src/gdb/solib-ia64-hpux.c,v
retrieving revision 1.5
diff -u -p -r1.5 solib-ia64-hpux.c
--- gdb/solib-ia64-hpux.c 9 Nov 2012 19:58:00 -0000 1.5
+++ gdb/solib-ia64-hpux.c 21 Dec 2012 19:41:04 -0000
@@ -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;
}
Index: gdb/solib-irix.c
===================================================================
RCS file: /cvs/src/src/gdb/solib-irix.c,v
retrieving revision 1.45
diff -u -p -r1.45 solib-irix.c
--- gdb/solib-irix.c 9 Nov 2012 19:58:00 -0000 1.45
+++ gdb/solib-irix.c 21 Dec 2012 19:41:06 -0000
@@ -653,4 +653,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;
}
Index: gdb/solib-osf.c
===================================================================
RCS file: /cvs/src/src/gdb/solib-osf.c,v
retrieving revision 1.37
diff -u -p -r1.37 solib-osf.c
--- gdb/solib-osf.c 24 May 2012 16:51:36 -0000 1.37
+++ gdb/solib-osf.c 21 Dec 2012 19:41:09 -0000
@@ -634,6 +634,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;
Index: gdb/solib-pa64.c
===================================================================
RCS file: /cvs/src/src/gdb/solib-pa64.c,v
retrieving revision 1.39
diff -u -p -r1.39 solib-pa64.c
--- gdb/solib-pa64.c 9 Nov 2012 19:58:01 -0000 1.39
+++ gdb/solib-pa64.c 21 Dec 2012 19:41:11 -0000
@@ -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));
}
Index: gdb/solib-som.c
===================================================================
RCS file: /cvs/src/src/gdb/solib-som.c,v
retrieving revision 1.38
diff -u -p -r1.38 solib-som.c
--- gdb/solib-som.c 9 Nov 2012 19:58:01 -0000 1.38
+++ gdb/solib-som.c 21 Dec 2012 19:41:13 -0000
@@ -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
Index: gdb/solib-spu.c
===================================================================
RCS file: /cvs/src/src/gdb/solib-spu.c,v
retrieving revision 1.23
diff -u -p -r1.23 solib-spu.c
--- gdb/solib-spu.c 9 Nov 2012 19:58:01 -0000 1.23
+++ gdb/solib-spu.c 21 Dec 2012 19:41:15 -0000
@@ -519,6 +519,7 @@ set_spu_solib_ops (struct gdbarch *gdbar
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);
Index: gdb/solib-sunos.c
===================================================================
RCS file: /cvs/src/src/gdb/solib-sunos.c,v
retrieving revision 1.50
diff -u -p -r1.50 solib-sunos.c
--- gdb/solib-sunos.c 9 Nov 2012 19:58:01 -0000 1.50
+++ gdb/solib-sunos.c 21 Dec 2012 19:41:17 -0000
@@ -739,6 +739,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;
Index: gdb/solib-target.c
===================================================================
RCS file: /cvs/src/src/gdb/solib-target.c,v
retrieving revision 1.25
diff -u -p -r1.25 solib-target.c
--- gdb/solib-target.c 14 Dec 2012 23:27:13 -0000 1.25
+++ gdb/solib-target.c 21 Dec 2012 19:41:19 -0000
@@ -25,6 +25,7 @@
#include "target.h"
#include "vec.h"
#include "solib-target.h"
+#include "solib.h"

#include "gdb_string.h"

@@ -501,6 +502,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. */