From: Pedro Alves <palves@redhat.com>
To: Zack Weinberg <zackw@panix.com>
Cc: GNU C Library <libc-alpha@sourceware.org>, gdb@sourceware.org
Subject: Re: [RFC PATCH 0/3] Pretty-printing for errno
Date: Wed, 06 Sep 2017 13:32:00 -0000 [thread overview]
Message-ID: <edcfb9d0-248c-fa10-583d-9a0512e4b091@redhat.com> (raw)
In-Reply-To: <CAKCAbMgsHH9bJCgELWY6R9sWaZvdqGjdfUFDLihx3mor8HofGw@mail.gmail.com>
On 09/06/2017 02:05 PM, Zack Weinberg wrote:
> On Tue, Sep 5, 2017 at 6:31 PM, Pedro Alves <palves@redhat.com> wrote:
>> On 09/05/2017 10:15 PM, Zack Weinberg wrote:
>>>
>>> I don't understand why thread-local variables are inaccessible on my
>>> perfectly ordinary x86_64-unknown-linux-gnu workstation (the base OS
>>> is Debian 'stretch'). Do you have any idea what might be wrong?
>>
>> I assume your test program isn't actually linked with -pthread?
>
> That is correct.
>
>> When you do "print errno" in this situation, because there's no
>> "#define errno ..." in sight, gdb ends up finding the real "errno" symbol,
>> which, even though the program isn't threaded, is a TLS symbol, and as such has
>> a DWARF location expression describing its location as an offset into the
>> thread-local block for the current thread. GDB needs to resolve that address, and
>> for threaded programs that is normally done with assistance from libthread_db.so.
>> The problem is then that libthread_db.so only works with programs that
>> link with libpthread.so, and if your test program is actually non-threaded,
>> it doesn't link with libpthread.so.
>
> I am not familiar with the glibc-side TLS implementation, nor with
> libthread_db.so, nor the code in GDB that uses libthread_db.so.
> However, reading the implementation of td_thr_tls_get_addr leads me to
> believe that that function is *supposed* to work even if libpthread.so
> has not been loaded into the 'inferior'. If it doesn't, perhaps that
> is a bug on our side. Do you know if GDB even tries? It's not obvious
> to me looking at linux-thread-db.c.
GDB only tries to load libthread_db.so if it detects libpthread.so loaded
in the inferior. gdb/linux-thread-db.c:thread_db_new_objfile is called for
every shared library found in the inferior.
However, if we hack gdb like this to force it to always try to
load libthread_db.so:
diff --git a/gdb/linux-thread-db.c b/gdb/linux-thread-db.c
index 6d98135..6cf634e 100644
--- a/gdb/linux-thread-db.c
+++ b/gdb/linux-thread-db.c
@@ -1000,8 +1000,11 @@ thread_db_new_objfile (struct objfile *objfile)
For dynamically linked executables, libpthread can be near the end
of the list of shared libraries to load, and in an app of several
thousand shared libraries, this can otherwise be painful. */
+#if 0
&& ((objfile->flags & OBJF_MAINLINE) != 0
- || libpthread_name_p (objfile_name (objfile))))
+ || libpthread_name_p (objfile_name (objfile)))
+#endif
+ )
check_for_thread_db ();
}
we get:
(gdb) set debug libthread-db 1
(gdb) nosharedlibrary
(gdb) sharedlibrary
Reading symbols from /lib64/libc.so.6...Reading symbols from /usr/lib/debug/usr/lib64/libc-2.22.so.debug...done.
done.
Trying host libthread_db library: libthread_db.so.1.
Host libthread_db.so.1 resolved to: /lib64/libthread_db.so.1.
td_ta_new failed: application not linked with libthread
thread_db_load_search returning 0
...
That "td_ta_new failed: application not linked with libthread"
error is output by thread_db_err_str in linux-thread-db.c. It's
just pretty-printing TD_NOLIBTHREAD. I.e., opening a connection
to libthread_db.so fails:
/* Now attempt to open a connection to the thread library. */
err = info->td_ta_new_p (&info->proc_handle, &info->thread_agent);
if (err != TD_OK)
{
Because lithread_db.so itself "rejects" the inferior.
If we repeat the exercise with a breakpoint on gdb's ps_pglobal_lookup
(from proc-service.c, which implements the libthread_db.so -> gdb
callback interface), we see:
[note to self: IWBN to make "set debug libthread-db 1" print these
look ups]
...
(gdb) sharedlibrary
Reading symbols from /lib64/libc.so.6...Reading symbols from /usr/lib/debug/usr/lib64/libc-2.22.so.debug...done.
done.
Trying host libthread_db library: libthread_db.so.1.
Host libthread_db.so.1 resolved to: /lib64/libthread_db.so.1.
Breakpoint 3, ps_pglobal_lookup (ph=0x1f04100, obj=0x7fffe58c50f8 "libpthread.so.0", name=0x7fffe58c5221 "nptl_version", sym_addr=0x7fffffffcf78)
at src/gdb/proc-service.c:113
113 struct inferior *inf = find_inferior_ptid (ph->ptid);
(top-gdb) c
Continuing.
td_ta_new failed: application not linked with libthread
thread_db_load_search returning 0
...
So in order to check whether the inferior is running a matching
glibc version, libthread_db.so looks for a "nptl_version" symbol,
which is only defined in libpthread.so, so not found in the inferior.
I did not try to hack gdb to return some address that happens
to point at a value that happens to match the expected version.
I think that for that experiment, hacking libthread_db.so itself
to skip the checks would likely be easier [and I can't afford to
do it right now].
>
>> A workaround specifically for errno, and only for live-process debugging [*]
>> is the "macro define" trick I had suggested before:
>>
>> (gdb) macro define errno (*__errno_location ())
>>
>> After that, "p errno" ends up calling __errno_location just
>> like when you compile the test program with -g3.
>
> Again, is it possible to do (the equivalent of) this from the
> initialization code of a pretty-printer module? Specifically, there
> already exists a Python function that's doing this:
>
> def register(objfile):
> """Register pretty printers for the current objfile."""
>
> printer = gdb.printing.RegexpCollectionPrettyPrinter("glibc-errno")
> printer.add_printer('error_t', r'^(?:__)?error_t', ErrnoPrinter)
>
> if objfile == None:
> objfile = gdb
>
> gdb.printing.register_pretty_printer(objfile, printer)
>
> called when the module is loaded; what would I need to add to that so
> that the macro is defined (if it isn't already)?
I'm hoping that other people more experienced with the gdb
Python API can chime in. My idea was just to call
gdb.execute ("macro define errno (*(int *) __errno_location ())")
somewhere around your Python code.
Thanks,
Pedro Alves
next prev parent reply other threads:[~2017-09-06 13:32 UTC|newest]
Thread overview: 28+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-06-22 22:45 Zack Weinberg
2017-06-22 22:45 ` [PATCH 1/3] Improve testing of GDB pretty-printers Zack Weinberg
2017-06-22 22:46 ` [PATCH 3/3] Add pretty-printer for errno Zack Weinberg
2017-06-22 22:46 ` [PATCH 2/3] Make error_t always int; make __errno_location return an __error_t Zack Weinberg
2017-06-29 15:48 ` [RFC PATCH 0/3] Pretty-printing for errno Phil Muldoon
2017-06-29 16:53 ` Pedro Alves
2017-06-29 17:02 ` Pedro Alves
2017-06-29 17:28 ` Pedro Alves
2017-06-30 0:28 ` Zack Weinberg
2017-06-30 16:38 ` Pedro Alves
2017-06-30 16:47 ` Pedro Alves
2017-06-30 17:27 ` Zack Weinberg
2017-06-30 18:11 ` Pedro Alves
2017-07-01 11:56 ` Pedro Alves
2017-07-13 2:30 ` Pedro Alves
2017-09-04 21:25 ` Pedro Alves
2017-09-05 21:15 ` Zack Weinberg
2017-09-05 22:32 ` Pedro Alves
2017-09-06 13:05 ` Zack Weinberg
2017-09-06 13:32 ` Pedro Alves [this message]
2017-09-06 21:03 ` Zack Weinberg
[not found] ` <2432779a-f146-1612-236e-84dde15c5d01@redhat.com>
2017-09-13 11:22 ` Using libthread_db.so with single-threaded programs, for TLS access (was: Re: [RFC PATCH 0/3] Pretty-printing for errno) Pedro Alves
2017-09-13 19:27 ` Philippe Waroquiers
2017-09-14 0:02 ` Using libthread_db.so with single-threaded programs, for TLS access Pedro Alves
2017-09-18 13:17 ` Carlos O'Donell
2017-09-18 14:28 ` Pedro Alves
2017-07-01 14:35 ` [RFC PATCH 0/3] Pretty-printing for errno Siddhesh Poyarekar
2017-07-04 15:54 ` Pedro Alves
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=edcfb9d0-248c-fa10-583d-9a0512e4b091@redhat.com \
--to=palves@redhat.com \
--cc=gdb@sourceware.org \
--cc=libc-alpha@sourceware.org \
--cc=zackw@panix.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox