[v5,7/8] Validate symbol file using build-id

Message ID 20140319223123.14668.95821.stgit@host1.jankratochvil.net
State Committed
Headers

Commit Message

Jan Kratochvil March 19, 2014, 10:31 p.m. UTC
  Hi,

consumer part of the "build-id" attribute.


Jan


gdb/
2014-02-26  Aleksandar Ristovski  <aristovski@qnx.com
	    Jan Kratochvil  <jan.kratochvil@redhat.com>

	Validate symbol file using build-id.
	* NEWS (Changes since GDB 7.7): Add 'set solib-build-id-force'
	and 'show solib-build-id-force'.  Add build-id attribute.
	* solib-darwin.c (_initialize_darwin_solib): Assign validate value.
	* 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-svr4.c: Include rsp-low.h.
	(NOTE_GNU_BUILD_ID_NAME): New define.
	(svr4_validate): New function.
	(library_list_start_library): Parse 'build-id' attribute.
	(svr4_library_attributes): Add 'build-id' attribute.
	(_initialize_svr4_solib): Assign validate value.
	* solib-target.c (solib.h): Include.
	(_initialize_solib_target): Assign validate value.
	* solib.c (solib_build_id_force, show_solib_build_id_force): New.
	(solib_map_sections): Use ops->validate.
	(clear_so): Free build_id.
	(default_solib_validate): New function.
	(_initialize_solib): Add "solib-build-id-force".
	* solib.h (default_solib_validate): New declaration.
	* solist.h (struct so_list): New fields 'build_idsz' and 'build_id'.
	(target_so_ops): New field 'validate'.

gdb/doc/
2014-03-02  Jan Kratochvil  <jan.kratochvil@redhat.com>

	* gdb.texinfo (Files): Add 'set solib-build-id-force'
	and 'show solib-build-id-force'.
---
 gdb/NEWS              |   10 ++++++
 gdb/doc/gdb.texinfo   |   38 ++++++++++++++++++++++
 gdb/solib-darwin.c    |    1 +
 gdb/solib-dsbt.c      |    1 +
 gdb/solib-frv.c       |    1 +
 gdb/solib-ia64-hpux.c |    1 +
 gdb/solib-irix.c      |    1 +
 gdb/solib-osf.c       |    1 +
 gdb/solib-pa64.c      |    1 +
 gdb/solib-som.c       |    1 +
 gdb/solib-spu.c       |    1 +
 gdb/solib-svr4.c      |   85 +++++++++++++++++++++++++++++++++++++++++++++++++
 gdb/solib-target.c    |    2 +
 gdb/solib.c           |   62 +++++++++++++++++++++++++++++++++++-
 gdb/solib.h           |    4 ++
 gdb/solist.h          |   21 ++++++++++++
 16 files changed, 230 insertions(+), 1 deletion(-)
  

Comments

Eli Zaretskii March 20, 2014, 3:51 a.m. UTC | #1
> From: Jan Kratochvil <jan.kratochvil@redhat.com>
> Cc: Aleksandar Ristovski <ARistovski@qnx.com>
> Date: Wed, 19 Mar 2014 23:31:23 +0100
> 
> consumer part of the "build-id" attribute.

Thanks.  I already approved the docs parts, right?
  
Jan Kratochvil March 20, 2014, 7:33 a.m. UTC | #2
Hi Eli,

On Thu, 20 Mar 2014 04:51:40 +0100, Eli Zaretskii wrote:
> Thanks.  I already approved the docs parts, right?

there remains unapproved the doc/gdb.texinfo part of this patch 7/8.
In this v5 series the text has been even changed due to the functionality
change:
 * svr4_validate() considers missing local build-id as not-a-match
(*)

Unfinished discussion with you about this doc/gdb.texinfo part is:
	https://sourceware.org/ml/gdb-patches/2014-03/msg00473.html
	Message-ID: <20140319223258.GA5398@host2.jankratochvil.net>


Thanks,
Jan


(*) Originally I wanted to check it in mostly as Aleksandar wrote it with
    various additions done possibly incrementally later.
    But given how complicated is to settle down on the messages and
    documentation of a part which was wrong (**) anyway I have decided to fix
    it rather all already during this first check-in.

(**) wrong as not a regression but imperfect functionality.
     I have found from practical using of non-upstreamed Fedora build-id
     patches that it is never right to load non-build-id file for build-id
     targer, in Fedora it is patch (not equivalent but similar functionality):
     http://pkgs.fedoraproject.org/cgit/gdb.git/tree/gdb-6.6-buildid-locate-solib-missing-ids.patch
  
Aleksandar Ristovski March 20, 2014, 1:13 p.m. UTC | #3
On 14-03-19 06:31 PM, Jan Kratochvil wrote:
> Hi,
>
> consumer part of the "build-id" attribute.
>
>
> Jan
>
>
> gdb/
> 2014-02-26  Aleksandar Ristovski  <aristovski@qnx.com
> 	    Jan Kratochvil  <jan.kratochvil@redhat.com>
>
> 	Validate symbol file using build-id.
> 	* NEWS (Changes since GDB 7.7): Add 'set solib-build-id-force'
> 	and 'show solib-build-id-force'.  Add build-id attribute.
> 	* solib-darwin.c (_initialize_darwin_solib): Assign validate value.
> 	* 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-svr4.c: Include rsp-low.h.
> 	(NOTE_GNU_BUILD_ID_NAME): New define.
> 	(svr4_validate): New function.
> 	(library_list_start_library): Parse 'build-id' attribute.
> 	(svr4_library_attributes): Add 'build-id' attribute.
> 	(_initialize_svr4_solib): Assign validate value.
> 	* solib-target.c (solib.h): Include.
> 	(_initialize_solib_target): Assign validate value.
> 	* solib.c (solib_build_id_force, show_solib_build_id_force): New.
> 	(solib_map_sections): Use ops->validate.
> 	(clear_so): Free build_id.
> 	(default_solib_validate): New function.
> 	(_initialize_solib): Add "solib-build-id-force".
> 	* solib.h (default_solib_validate): New declaration.
> 	* solist.h (struct so_list): New fields 'build_idsz' and 'build_id'.
> 	(target_so_ops): New field 'validate'.
>
> gdb/doc/
> 2014-03-02  Jan Kratochvil  <jan.kratochvil@redhat.com>
>
> 	* gdb.texinfo (Files): Add 'set solib-build-id-force'
> 	and 'show solib-build-id-force'.
> ---
>   gdb/NEWS              |   10 ++++++
>   gdb/doc/gdb.texinfo   |   38 ++++++++++++++++++++++
>   gdb/solib-darwin.c    |    1 +
>   gdb/solib-dsbt.c      |    1 +
>   gdb/solib-frv.c       |    1 +
>   gdb/solib-ia64-hpux.c |    1 +
>   gdb/solib-irix.c      |    1 +
>   gdb/solib-osf.c       |    1 +
>   gdb/solib-pa64.c      |    1 +
>   gdb/solib-som.c       |    1 +
>   gdb/solib-spu.c       |    1 +
>   gdb/solib-svr4.c      |   85 +++++++++++++++++++++++++++++++++++++++++++++++++
>   gdb/solib-target.c    |    2 +
>   gdb/solib.c           |   62 +++++++++++++++++++++++++++++++++++-
>   gdb/solib.h           |    4 ++
>   gdb/solist.h          |   21 ++++++++++++
>   16 files changed, 230 insertions(+), 1 deletion(-)
>
> diff --git a/gdb/NEWS b/gdb/NEWS
> index 2a384ba..629cc13 100644
> --- a/gdb/NEWS
> +++ b/gdb/NEWS
> @@ -43,6 +43,12 @@ maint ada show ignore-descriptive-types
>     the user manual for more details on descriptive types and the intended
>     usage of this option.
>
> +set solib-build-id-force (on|off)
> +show solib-build-id-force
> +  Inferior shared library and symbol file may contain unique build-id.
> +  If both build-ids are present but they do not match then this setting
> +  enables (on) or disables (off) loading of such symbol file.
> +
>   * New features in the GDB remote stub, GDBserver
>
>     ** New option --debug-format=option1[,option2,...] allows one to add
> @@ -51,6 +57,10 @@ maint ada show ignore-descriptive-types
>        Timestamps can also be turned on with the
>        "monitor set debug-format timestamps" command from GDB.
>
> +  ** 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.
> +
>   * The 'record instruction-history' command now starts counting instructions
>     at one.  This also affects the instruction ranges reported by the
>     'record function-call-history' command when given the /i modifier.
> diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
> index b1b29bd..a4af3ec 100644
> --- a/gdb/doc/gdb.texinfo
> +++ b/gdb/doc/gdb.texinfo
> @@ -17114,6 +17114,44 @@ libraries that were loaded by explicit user requests are not
>   discarded.
>   @end table
>
> +@table @code
> +@kindex set solib-build-id-force
> +@cindex override @value{GDBN} build-id check
> +@item set solib-build-id-force @var{mode}
> +Setting to override @value{GDBN} build-id check.
> +
> +Inferior shared libraries and symbol files may contain unique build-id.
> +By default @value{GDBN} will ignore symbol files with non-matching build-id
> +while printing:
> +
> +@smallexample
> +  warning: Shared object "libfoo.so.1" could not be validated (remote
> +  build ID 2bc1745e does not match local build ID a08f8767) and will be


I am not sure 'remote' adds any clarity here, on-contrary, I think it 
will confuse. This could all be happening in local scenario as well. The 
gist should be: inferior so build-id (i.e. build-id of the shared object 
loaded in the inferior memory) does not match build-id of the so gdb 
loaded to get symbols.


> +  ignored; or use 'set solib-build-id-force'.
> +@end smallexample
> +
> +Turning on this setting would load such symbol file while still printing:
> +
> +@smallexample
> +  warning: Shared object "libfoo.so.1" could not be validated (remote
> +  build ID 2bc1745e does not match local build ID a08f8767) but it is
> +  being loaded due to 'set solib-build-id-force'.
> +@end smallexample

The same here

> +
> +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{on}) or
> +disables (@var{mode} is @code{off}) 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{off}.

and here. I think 'inferior' would be a lot more suitable reference than 
"remote system".


---
Aleksandar Ristovski
QNX Software Systems
  
Eli Zaretskii March 20, 2014, 5:28 p.m. UTC | #4
> Date: Thu, 20 Mar 2014 08:33:50 +0100
> From: Jan Kratochvil <jan.kratochvil@redhat.com>
> Cc: gdb-patches@sourceware.org, ARistovski@qnx.com
> 
> Hi Eli,
> 
> On Thu, 20 Mar 2014 04:51:40 +0100, Eli Zaretskii wrote:
> > Thanks.  I already approved the docs parts, right?
> 
> there remains unapproved the doc/gdb.texinfo part of this patch 7/8.
> In this v5 series the text has been even changed due to the functionality
> change:
>  * svr4_validate() considers missing local build-id as not-a-match
> (*)
> 
> Unfinished discussion with you about this doc/gdb.texinfo part is:
> 	https://sourceware.org/ml/gdb-patches/2014-03/msg00473.html
> 	Message-ID: <20140319223258.GA5398@host2.jankratochvil.net>

Yes, but in https://sourceware.org/ml/gdb-patches/2014-03/msg00219.html
I suggested an addition, which somehow didn't make it here.  The only
change I see is in the wording of the warning message you quote.
  
Jan Kratochvil March 21, 2014, 4:58 p.m. UTC | #5
On Thu, 20 Mar 2014 18:28:37 +0100, Eli Zaretskii wrote:
> Yes, but in https://sourceware.org/ml/gdb-patches/2014-03/msg00219.html
> I suggested an addition, which somehow didn't make it here.  The only
> change I see is in the wording of the warning message you quote.

You are right, I somehow forgot about that mail, replied to it now.


Thanks,
Jan
  
Jan Kratochvil March 21, 2014, 4:58 p.m. UTC | #6
On Thu, 20 Mar 2014 14:13:06 +0100, Aleksandar Ristovski wrote:
> On 14-03-19 06:31 PM, Jan Kratochvil wrote:
> >+@smallexample
> >+  warning: Shared object "libfoo.so.1" could not be validated (remote
> >+  build ID 2bc1745e does not match local build ID a08f8767) and will be
> 
> I am not sure 'remote' adds any clarity here, on-contrary, I think
> it will confuse. This could all be happening in local scenario as
> well. The gist should be: inferior so build-id (i.e. build-id of the
> shared object loaded in the inferior memory) does not match build-id
> of the so gdb loaded to get symbols.

Therefore:
s/remote/inferior/
s/local/symbol file/


------------------------------------------------------------------------------
@smallexample
  warning: Shared object "libfoo.so.1" could not be validated (inferior
  build ID 2bc1745e does not match symbol file build ID a08f8767) and 
  will be ignored; or use 'set solib-build-id-force'.
@end smallexample

Turning on this setting would load such symbol file while still printing:

@smallexample
  warning: Shared object "libfoo.so.1" could not be validated (inferior
  build ID 2bc1745e is not identical to symbol file build ID a08f8767) 
  but it is being loaded due to 'set solib-build-id-force'.
@end smallexample
------------------------------------------------------------------------------


> >+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{on}) or
> >+disables (@var{mode} is @code{off}) 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{off}.
> 
> and here. I think 'inferior' would be a lot more suitable reference
> than "remote system".

Done.


Thanks,
Jan
  
Aleksandar Ristovski March 21, 2014, 5:08 p.m. UTC | #7
On 14-03-21 12:58 PM, Jan Kratochvil wrote:
> On Thu, 20 Mar 2014 14:13:06 +0100, Aleksandar Ristovski wrote:
>> On 14-03-19 06:31 PM, Jan Kratochvil wrote:
>>> +@smallexample
>>> +  warning: Shared object "libfoo.so.1" could not be validated (remote
>>> +  build ID 2bc1745e does not match local build ID a08f8767) and will be
>>
>> I am not sure 'remote' adds any clarity here, on-contrary, I think
>> it will confuse. This could all be happening in local scenario as
>> well. The gist should be: inferior so build-id (i.e. build-id of the
>> shared object loaded in the inferior memory) does not match build-id
>> of the so gdb loaded to get symbols.
>
> Therefore:
> s/remote/inferior/
> s/local/symbol file/


Yes, I think this is better, thank you.

----
Aleksandar Ristovski
QNX Software Systems
  
Tom Tromey May 20, 2014, 2:51 p.m. UTC | #8
>>>>> "Jan" == Jan Kratochvil <jan.kratochvil@redhat.com> writes:

Jan> consumer part of the "build-id" attribute.

This is ok.

Tom
  

Patch

diff --git a/gdb/NEWS b/gdb/NEWS
index 2a384ba..629cc13 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -43,6 +43,12 @@  maint ada show ignore-descriptive-types
   the user manual for more details on descriptive types and the intended
   usage of this option.
 
+set solib-build-id-force (on|off)
+show solib-build-id-force
+  Inferior shared library and symbol file may contain unique build-id.
+  If both build-ids are present but they do not match then this setting
+  enables (on) or disables (off) loading of such symbol file.
+
 * New features in the GDB remote stub, GDBserver
 
   ** New option --debug-format=option1[,option2,...] allows one to add
@@ -51,6 +57,10 @@  maint ada show ignore-descriptive-types
      Timestamps can also be turned on with the
      "monitor set debug-format timestamps" command from GDB.
 
+  ** 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.
+
 * The 'record instruction-history' command now starts counting instructions
   at one.  This also affects the instruction ranges reported by the
   'record function-call-history' command when given the /i modifier.
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index b1b29bd..a4af3ec 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -17114,6 +17114,44 @@  libraries that were loaded by explicit user requests are not
 discarded.
 @end table
 
+@table @code
+@kindex set solib-build-id-force
+@cindex override @value{GDBN} build-id check
+@item set solib-build-id-force @var{mode}
+Setting to override @value{GDBN} build-id check.
+
+Inferior shared libraries and symbol files may contain unique build-id.
+By default @value{GDBN} will ignore symbol files with non-matching build-id
+while printing:
+
+@smallexample
+  warning: Shared object "libfoo.so.1" could not be validated (remote
+  build ID 2bc1745e does not match local build ID a08f8767) and will be
+  ignored; or use 'set solib-build-id-force'.
+@end smallexample
+
+Turning on this setting would load such symbol file while still printing:
+
+@smallexample
+  warning: Shared object "libfoo.so.1" could not be validated (remote
+  build ID 2bc1745e does not match local build ID a08f8767) but it is
+  being loaded due to 'set solib-build-id-force'.
+@end smallexample
+
+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{on}) or
+disables (@var{mode} is @code{off}) 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{off}.
+
+Loading non-matching symbol file may confuse debugging including breakage
+of backtrace output.
+
+@kindex show solib-build-id-force
+@item show solib-build-id-force
+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
diff --git a/gdb/solib-darwin.c b/gdb/solib-darwin.c
index a9989ea..11de7cd 100644
--- a/gdb/solib-darwin.c
+++ b/gdb/solib-darwin.c
@@ -653,4 +653,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 = default_solib_validate;
 }
diff --git a/gdb/solib-dsbt.c b/gdb/solib-dsbt.c
index 0217a94..35223dd 100644
--- a/gdb/solib-dsbt.c
+++ b/gdb/solib-dsbt.c
@@ -1078,6 +1078,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 = default_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 9724a3c..18a4aba 100644
--- a/gdb/solib-frv.c
+++ b/gdb/solib-frv.c
@@ -1181,6 +1181,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 = default_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 b53caa8..a39bb03 100644
--- a/gdb/solib-ia64-hpux.c
+++ b/gdb/solib-ia64-hpux.c
@@ -688,6 +688,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 = default_solib_validate;
 
   return ops;
 }
diff --git a/gdb/solib-irix.c b/gdb/solib-irix.c
index 6266ee0..1f126a3 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 = default_solib_validate;
 }
diff --git a/gdb/solib-osf.c b/gdb/solib-osf.c
index 90a26e8..5490f83 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 = default_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 099e1e7..da8a294 100644
--- a/gdb/solib-pa64.c
+++ b/gdb/solib-pa64.c
@@ -621,6 +621,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 = default_solib_validate;
 
   memset (&dld_cache, 0, sizeof (dld_cache));
 }
diff --git a/gdb/solib-som.c b/gdb/solib-som.c
index cba50d1..ed2cbfe 100644
--- a/gdb/solib-som.c
+++ b/gdb/solib-som.c
@@ -816,6 +816,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 = default_solib_validate;
 }
 
 void
diff --git a/gdb/solib-spu.c b/gdb/solib-spu.c
index 1c574b5..8385205 100644
--- a/gdb/solib-spu.c
+++ b/gdb/solib-spu.c
@@ -521,6 +521,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 = default_solib_validate;
     }
 
   set_solib_ops (gdbarch, &spu_so_ops);
diff --git a/gdb/solib-svr4.c b/gdb/solib-svr4.c
index 0da5692..65d8746 100644
--- a/gdb/solib-svr4.c
+++ b/gdb/solib-svr4.c
@@ -47,6 +47,9 @@ 
 #include "exceptions.h"
 #include "gdb_bfd.h"
 #include "probe.h"
+#include "rsp-low.h"
+
+#define NOTE_GNU_BUILD_ID_NAME  ".note.gnu.build-id"
 
 static struct link_map_offsets *svr4_fetch_link_map_offsets (void);
 static int svr4_have_link_map_offsets (void);
@@ -959,6 +962,64 @@  svr4_keep_data_in_core (CORE_ADDR vaddr, unsigned long size)
   return (name_lm >= vaddr && name_lm < vaddr + size);
 }
 
+/* Validate SO by comparing build-id from the associated bfd and
+   corresponding build-id from target memory.  */
+
+static char *
+svr4_validate (const struct so_list *const so)
+{
+  bfd_byte *local_id;
+  size_t local_idsz;
+
+  gdb_assert (so != NULL);
+
+  /* Target doesn't support reporting the build ID or the remote shared library
+     does not have build ID.  */
+  if (so->build_id == NULL)
+    return NULL;
+
+  /* Build ID may be present in the local file, just GDB is unable to retrieve
+     it.  As it has been reported by gdbserver it is not FSF gdbserver.  */
+  if (so->abfd == NULL
+      || !bfd_check_format (so->abfd, bfd_object)
+      || bfd_get_flavour (so->abfd) != bfd_target_elf_flavour)
+    return NULL;
+
+  /* GDB has verified the local file really does not contain the build ID.  */
+  if (elf_tdata (so->abfd)->build_id == NULL)
+    {
+      char *remote_hex;
+
+      remote_hex = alloca (so->build_idsz * 2 + 1);
+      bin2hex (so->build_id, remote_hex, so->build_idsz);
+
+      return xstrprintf (_("remote build ID is %s "
+			   "but local file does not have build ID"),
+			 remote_hex);
+    }
+
+  local_id = elf_tdata (so->abfd)->build_id->data;
+  local_idsz = elf_tdata (so->abfd)->build_id->size;
+
+  if (so->build_idsz != local_idsz
+      || memcmp (so->build_id, local_id, so->build_idsz) != 0)
+    {
+      char *remote_hex, *local_hex;
+
+      remote_hex = alloca (so->build_idsz * 2 + 1);
+      bin2hex (so->build_id, remote_hex, so->build_idsz);
+      local_hex = alloca (local_idsz * 2 + 1);
+      bin2hex (local_id, local_hex, local_idsz);
+
+      return xstrprintf (_("remote build ID %s "
+			   "does not match local build ID %s"),
+			 remote_hex, local_hex);
+    }
+
+  /* Both build IDs are present and they match.  */
+  return NULL;
+}
+
 /* Implement the "open_symbol_file_object" target_so_ops method.
 
    If no open symbol file, attempt to locate and open the main symbol
@@ -1124,6 +1185,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 = XCNEW (struct so_list);
@@ -1135,6 +1199,25 @@  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)
+    {
+      const size_t hex_build_id_len = strlen (hex_build_id);
+
+      if (hex_build_id_len > 0 && (hex_build_id_len & 1U) == 0)
+	{
+	  const size_t build_idsz = hex_build_id_len / 2;
+
+	  new_elem->build_id = xmalloc (build_idsz);
+	  new_elem->build_idsz = hex2bin (hex_build_id, new_elem->build_id,
+					  build_idsz);
+	  if (new_elem->build_idsz != 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;
@@ -1169,6 +1252,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_OPTIONAL, NULL, NULL },
   { NULL, GDB_XML_AF_NONE, NULL, NULL }
 };
 
@@ -3166,4 +3250,5 @@  _initialize_svr4_solib (void)
   svr4_so_ops.keep_data_in_core = svr4_keep_data_in_core;
   svr4_so_ops.update_breakpoints = svr4_update_solib_event_breakpoints;
   svr4_so_ops.handle_event = svr4_handle_solib_event;
+  svr4_so_ops.validate = svr4_validate;
 }
diff --git a/gdb/solib-target.c b/gdb/solib-target.c
index bb34e4b..23b2d06 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 <string.h>
 
@@ -502,6 +503,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 = default_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 3350bfd..83366ae 100644
--- a/gdb/solib.c
+++ b/gdb/solib.c
@@ -454,6 +454,20 @@  solib_bfd_open (char *pathname)
   return abfd;
 }
 
+/* Boolean for command 'set solib-build-id-force'.  */
+static int solib_build_id_force = 0;
+
+/* Implement 'show solib-build-id-force'.  */
+
+static void
+show_solib_build_id_force (struct ui_file *file, int from_tty,
+			   struct cmd_list_element *c, const char *value)
+{
+  fprintf_filtered (file, _("Loading of shared libraries "
+			    "with non-matching build-id is %s.\n"),
+		    value);
+}
+
 /* Given a pointer to one of the shared objects in our list of mapped
    objects, use the recorded name to open a bfd descriptor for the
    object, build a section table, relocate all the section addresses
@@ -470,7 +484,7 @@  static int
 solib_map_sections (struct so_list *so)
 {
   const struct target_so_ops *ops = solib_ops (target_gdbarch ());
-  char *filename;
+  char *filename, *validate_error;
   struct target_section *p;
   struct cleanup *old_chain;
   bfd *abfd;
@@ -486,6 +500,27 @@  solib_map_sections (struct so_list *so)
   /* Leave bfd open, core_xfer_memory and "info files" need it.  */
   so->abfd = abfd;
 
+  gdb_assert (ops->validate != NULL);
+
+  validate_error = ops->validate (so);
+  if (validate_error != NULL)
+    {
+      if (!solib_build_id_force)
+	{
+	  warning (_("Shared object \"%s\" could not be validated (%s) and "
+	             "will be ignored; or use 'set solib-build-id-force'."),
+		   so->so_name, validate_error);
+	  xfree (validate_error);
+	  gdb_bfd_unref (so->abfd);
+	  so->abfd = NULL;
+	  return 0;
+	}
+      warning (_("Shared object \"%s\" could not be validated (%s) "
+		 "but it is being loaded due to 'set solib-build-id-force'."),
+	       so->so_name, validate_error);
+      xfree (validate_error);
+    }
+
   /* Copy the full path name into so_name, allowing symbol_file_add
      to find it later.  This also affects the =library-loaded GDB/MI
      event, and in particular the part of that notification providing
@@ -562,6 +597,9 @@  clear_so (struct so_list *so)
      of the symbol file.  */
   strcpy (so->so_name, so->so_original_name);
 
+  xfree (so->build_id);
+  so->build_id = NULL;
+
   /* Do the same for target-specific data.  */
   if (ops->clear_so != NULL)
     ops->clear_so (so);
@@ -1523,6 +1561,14 @@  remove_user_added_objfile (struct objfile *objfile)
     }
 }
 
+/* Default implementation does not perform any validation.  */
+
+char *
+default_solib_validate (const struct so_list *const so)
+{
+  return NULL; /* No validation.  */
+}
+
 extern initialize_file_ftype _initialize_solib; /* -Wmissing-prototypes */
 
 void
@@ -1579,4 +1625,18 @@  PATH and LD_LIBRARY_PATH."),
 				     reload_shared_libraries,
 				     show_solib_search_path,
 				     &setlist, &showlist);
+
+  add_setshow_boolean_cmd ("solib-build-id-force", class_support,
+			   &solib_build_id_force, _("\
+Set loading of shared libraries with non-matching build-id."), _("\
+Show loading of shared libraries with non-matching build-id."), _("\
+Inferior shared library and symbol file may contain unique build-id.\n\
+If both build-ids are present but they do not match then this setting\n\
+enables (on) or disables (off) loading of such symbol file.\n\
+Loading non-matching symbol file may confuse debugging including breakage\n\
+of backtrace output."),
+			   NULL,
+			   show_solib_build_id_force,
+			   &setlist, &showlist);
+
 }
diff --git a/gdb/solib.h b/gdb/solib.h
index 29fe8f7..ab0dccd 100644
--- a/gdb/solib.h
+++ b/gdb/solib.h
@@ -98,4 +98,8 @@  extern void update_solib_breakpoints (void);
 
 extern void handle_solib_event (void);
 
+/* Default validation always returns 1.  */
+
+extern char *default_solib_validate (const struct so_list *so);
+
 #endif /* SOLIB_H */
diff --git a/gdb/solist.h b/gdb/solist.h
index ac1b1a7..10b67ee 100644
--- a/gdb/solist.h
+++ b/gdb/solist.h
@@ -75,6 +75,22 @@  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, contains verbatim contents of
+       .note.gnu.build-id including note header.  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 build-id of the associated bfd.  In a normal
+       scenario, this so would soon lose its abfd due to failed
+       validation.
+       Reading target memory should be done by following execution view
+       of the binary (following program headers in the case of ELF).
+       Computing address from the linking view (following ELF section
+       headers) may give incorrect build-id memory address despite the
+       symbols still match.
+       Such an example is a prelinked vs.  unprelinked i386 ELF file.  */
+    size_t build_idsz;
+    gdb_byte *build_id;
   };
 
 struct target_so_ops
@@ -168,6 +184,11 @@  struct target_so_ops
        NULL, in which case no specific preprocessing is necessary
        for this target.  */
     void (*handle_event) (void);
+
+    /* Return NULL if SO does match target SO it is supposed to
+       represent.  Otherwise return string describing why it does not match.
+       Caller has to free the string.  */
+    char *(*validate) (const struct so_list *so);
   };
 
 /* Free the memory associated with a (so_list *).  */