From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 9525 invoked by alias); 4 Oct 2009 20:32:39 -0000 Received: (qmail 9515 invoked by uid 22791); 4 Oct 2009 20:32:38 -0000 X-SWARE-Spam-Status: No, hits=-2.3 required=5.0 tests=AWL,BAYES_00,SPF_PASS X-Spam-Check-By: sourceware.org Received: from mail.codesourcery.com (HELO mail.codesourcery.com) (65.74.133.4) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Sun, 04 Oct 2009 20:32:33 +0000 Received: (qmail 5704 invoked from network); 4 Oct 2009 20:32:31 -0000 Received: from unknown (HELO orlando) (pedro@127.0.0.2) by mail.codesourcery.com with ESMTPA; 4 Oct 2009 20:32:31 -0000 From: Pedro Alves To: Paul Pluzhnikov Subject: Re: [patch] Allow gdbserver to dynamically lookup libthread_db.so.1 Date: Sun, 04 Oct 2009 20:32:00 -0000 User-Agent: KMail/1.9.10 Cc: gdb-patches@sourceware.org, dje@google.com References: <20090902163344.833F476568@localhost> <8ac60eac0909021015u37d1a6e2u1ae88dd35d00d2b9@mail.gmail.com> <8ac60eac0910021651o38990564ue7a65a870c14d00b@mail.gmail.com> In-Reply-To: <8ac60eac0910021651o38990564ue7a65a870c14d00b@mail.gmail.com> MIME-Version: 1.0 Content-Type: text/plain; charset="iso-8859-1" Content-Transfer-Encoding: quoted-printable Content-Disposition: inline Message-Id: <200910042132.23246.pedro@codesourcery.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: 2009-10/txt/msg00102.txt.bz2 On Saturday 03 October 2009 00:51:22, Paul Pluzhnikov wrote: > On Wed, Sep 2, 2009 at 10:15 AM, Paul Pluzhnikov = wrote: > > On Wed, Sep 2, 2009 at 9:47 AM, Pedro Alves wro= te: > > > >> Since you're touching this, how about loading a thread_db per-process > >> like gdb/linux-thread-db.c already does? > > > > Oh, I've had this patch locally for so long, I didn't realize gdbserver > > is now multi-process as well. Will fix. >=20 > Here is the fix. Thanks much. This is close. I take it you only care for extended-remote? How is the user supposed to tweak the new setting with plain remote? "tar remote; monitor foo; c" ? I don't think that would work with "gdbserver --attach". > Index: gdbserver/acinclude.m4 > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D > RCS file: /cvs/src/src/gdb/gdbserver/acinclude.m4,v > retrieving revision 1.7 > diff -u -p -u -r1.7 acinclude.m4 > --- gdbserver/acinclude.m4=A0=A0=A0=A0=A0=A05 Jun 2008 22:36:57 -0000=A0= =A0=A0=A0=A0=A0=A01.7 > +++ gdbserver/acinclude.m4=A0=A0=A0=A0=A0=A02 Oct 2009 23:49:31 -0000 > @@ -22,7 +22,7 @@ AC_DEFUN([SRV_CHECK_THREAD_DB], > =A0 =A0 void ps_get_thread_area() {} > =A0 =A0 void ps_getpid() {}], > =A0 =A0[td_ta_new();], > - =A0[srv_cv_thread_db=3D"-lthread_db"], > + =A0[srv_cv_thread_db=3D"-ldl"], > =A0 =A0[srv_cv_thread_db=3Dno > =A0 > =A0 if test "$prefix" =3D "/usr" || test "$prefix" =3D "NONE"; then > @@ -42,28 +42,9 @@ AC_DEFUN([SRV_CHECK_THREAD_DB], > =A0 =A0 void ps_get_thread_area() {} > =A0 =A0 void ps_getpid() {}], > =A0 =A0[td_ta_new();], > - =A0[srv_cv_thread_db=3D"$thread_db"], > + =A0[srv_cv_thread_db=3D"-ldl"], > =A0 =A0[srv_cv_thread_db=3Dno]) > =A0 =A0]) > =A0 LIBS=3D"$old_LIBS" This doesn't make sense. > Index: gdbserver/linux-low.h > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D > RCS file: /cvs/src/src/gdb/gdbserver/linux-low.h,v > retrieving revision 1.32 > diff -u -p -u -r1.32 linux-low.h > --- gdbserver/linux-low.h=A0=A0=A0=A0=A0=A0=A030 Jun 2009 16:35:25 -0000= =A0=A0=A0=A0=A0=A01.32 > +++ gdbserver/linux-low.h=A0=A0=A0=A0=A0=A0=A02 Oct 2009 23:49:31 -0000 > @@ -57,6 +57,32 @@ struct process_info_private > =A0 =A0/* Connection to the libthread_db library. =A0*/ > =A0 =A0td_thragent_t *thread_agent; > =A0 > + =A0/* Handle of the libthread_db from dlopen. =A0*/ > + =A0void *handle; > + > + =A0/* Addresses of libthread_db functions. =A0*/ > + =A0td_err_e (*td_ta_new_p) (struct ps_prochandle * ps, td_thragent_t **= ta); > + =A0td_err_e (*td_ta_event_getmsg_p) (const td_thragent_t *ta, > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0 =A0 =A0td_event_msg_t *msg); > + =A0td_err_e (*td_ta_set_event_p) (const td_thragent_t *ta, > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0 td_thr_events_t *event); > + =A0td_err_e (*td_ta_event_addr_p) (const td_thragent_t *ta, > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0 =A0td_event_e event, td_notify_t *ptr); > + =A0td_err_e (*td_ta_map_lwp2thr_p) (const td_thragent_t *ta, lwpid_t lw= pid, > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0 =A0 td_thrhandle_t *th); > + =A0td_err_e (*td_thr_get_info_p) (const td_thrhandle_t *th, > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0 td_thrinfo_t *infop); > + =A0td_err_e (*td_thr_event_enable_p) (const td_thrhandle_t *th, int eve= nt); > + =A0td_err_e (*td_ta_thr_iter_p) (const td_thragent_t *ta, > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0td_thr_iter_f *callback, void *cbdata_p, > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0td_thr_state_e state, int ti_pri, > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0sigset_t *ti_sigmask_p, > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0unsigned int ti_user_flags); > + =A0td_err_e (*td_thr_tls_get_addr_p) (const td_thrhandle_t *th, > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0 =A0 =A0 void *map_address, > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0 =A0 =A0 size_t offset, void **address); > + =A0const char ** (*td_symbol_list_p) (void); > + Although gdbserver doesn't have a target stack concept, let's try to keep t= he layers a bit separate. Could you please make this a new (private) structure in thread-db.c, and then have a new pointer here, say process_info_private->thread_db into such an object? > =A0 =A0/* Arch-specific additions. =A0*/ > =A0 =A0struct arch_process_info *arch_private; > =A0}; > Index: gdbserver/server.c > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D > RCS file: /cvs/src/src/gdb/gdbserver/server.c,v > retrieving revision 1.102 > diff -u -p -u -r1.102 server.c > --- gdbserver/server.c=A0=A030 Jun 2009 16:35:25 -0000=A0=A0=A0=A0=A0=A01= .102 > +++ gdbserver/server.c=A0=A02 Oct 2009 23:49:31 -0000 > @@ -32,6 +32,8 @@ > =A0#include > =A0#endif > =A0 > +#include > + > =A0ptid_t cont_thread; > =A0ptid_t general_thread; > =A0ptid_t step_thread; > @@ -51,6 +53,10 @@ static char **program_argv, **wrapper_ar > =A0 =A0 was originally used to debug LinuxThreads support. =A0*/ > =A0int debug_threads; > =A0 > +/* If not NULL, a colon-separated list of paths to use while looking for > + =A0 libthread_db. =A0*/ > +char *libthread_db_search_path; We're now leaking target specific code into gdbserver's common bits. This will definitely not make sense to have on a Windows build of gdbserver. Can I convince you to add a target hook to handle monitor commands, and move this handling to thread-db.c? That's the simplest. Even better would be to have some way to register monitor commands with a callback, similar to gdb commands, but much simpler. But I'd be happy with the target method for now. > Index: gdbserver/thread-db.c > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D > RCS file: /cvs/src/src/gdb/gdbserver/thread-db.c,v > retrieving revision 1.23 > diff -u -p -u -r1.23 thread-db.c > --- gdbserver/thread-db.c=A0=A0=A0=A0=A0=A0=A03 Apr 2009 20:15:51 -0000= =A0=A0=A0=A0=A0=A0=A01.23 > +++ gdbserver/thread-db.c=A0=A0=A0=A0=A0=A0=A02 Oct 2009 23:49:31 -0000 > @@ -233,7 +222,7 @@ find_one_thread (ptid_t ptid) > =A0 =A0td_err_e err; > =A0 =A0struct thread_info *inferior; > =A0 =A0struct lwp_info *lwp; > - =A0struct process_info_private *proc; > + =A0struct process_info_private *proc =3D current_process()->private; Missing space before '()'. There are other instances of this. > =A0 =A0/* If the thread layer is not (yet) initialized, fail. =A0*/ > - =A0if (!get_thread_process (thread)->all_symbols_looked_up) > + =A0if (proc->all_symbols_looked_up =3D=3D 0) > + =A0 =A0return TD_ERR; Please keep using ! for boolean's. > + > + =A0if (priv->td_thr_tls_get_addr_p =3D=3D NULL) > =A0 =A0 =A0return TD_ERR; Shouldn't this be -1 ? As in ... > -#else > - =A0return -1; > -#endif ... this? < 0 here means unsupported, see server.c. > +} > + > +static int > +try_thread_db_load_1 (void *handle) > +{ > + =A0td_err_e err; > + =A0struct process_info *proc =3D current_process (); > + =A0struct process_info_private *priv =3D proc->private; > + > + =A0/* Initialize pointers to the dynamic library functions we will use. > + =A0 =A0 Essential functions first. =A0*/ > + > +#define CHK(required, a)=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0\ > + =A0if ((a) =3D=3D NULL) {=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0\ > + =A0 =A0if (debug_threads) {=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0\ > + =A0 =A0 =A0fprintf (stderr, "dlsym: %s\n", dlerror ());=A0=A0=A0=A0=A0\ > + =A0 =A0}=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0\ > + =A0 =A0if (required)=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0\ > + =A0 =A0 =A0return 0;=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0= =A0=A0=A0=A0=A0=A0\ > + =A0} Even though people shouldn't stare at this for too long (it may cause rare forms of brain rash), please make this follow the code standards. '{' on new line. I'd prefer to see this wrapped on do {} while (0). Dangling if's raise eyebrows. > + > + =A0CHK (1, priv->td_ta_new_p =3D dlsym (handle, "td_ta_new")); > + > + =A0/* Attempt to open a connection to the thread library. =A0*/ > + =A0err =3D priv->td_ta_new_p (&priv->proc_handle, &priv->thread_agent); > + =A0if (err !=3D TD_OK) > + =A0 =A0{ > + =A0 =A0 =A0priv->td_ta_new_p =3D NULL; > + =A0 =A0 =A0if (debug_threads) > +=A0=A0=A0=A0=A0=A0=A0fprintf (stderr, "td_ta_new(): %s\n", thread_db_err= _str (err)); > + =A0 =A0 =A0return 0; > + =A0 =A0} > + > + =A0CHK (1, priv->td_ta_map_lwp2thr_p =3D dlsym (handle, "td_ta_map_lwp2= thr")); > + =A0CHK (1, priv->td_thr_get_info_p =3D dlsym (handle, "td_thr_get_info"= )); > + =A0CHK (1, priv->td_ta_thr_iter_p =3D dlsym (handle, "td_ta_thr_iter")); > + =A0CHK (1, priv->td_symbol_list_p =3D dlsym (handle, "td_symbol_list")); > + > + =A0/* This is required only when thread_db_use_events is on. =A0*/ > + =A0CHK (thread_db_use_events, > + =A0 =A0 =A0 priv->td_thr_event_enable_p =3D dlsym (handle, "td_thr_even= t_enable")); > + > + =A0/* These are not essential. =A0*/ > + =A0CHK (0, priv->td_ta_event_addr_p =3D dlsym (handle, "td_ta_event_add= r")); > + =A0CHK (0, priv->td_ta_set_event_p =3D dlsym (handle, "td_ta_set_event"= )); > + =A0CHK (0, priv->td_ta_event_getmsg_p =3D dlsym (handle, "td_ta_event_g= etmsg")); > + =A0CHK (0, priv->td_thr_tls_get_addr_p =3D dlsym (handle, "td_thr_tls_g= et_addr")); > + > +#undef CHK Looking at the equivalent code in gdb/linux-thread-db.c, I don't know that it's less readable there anyway, and I don't think the case of finding just a couple of the required symbols (and dumping that to debug output) is something we expect to find. Just MHO. > + > + =A0return 1; > +} > + > + > +static int > +thread_db_load_search () ^ (void) please. > +{ > + =A0char path[PATH_MAX]; > + =A0const char *search_path; > + =A0int rc =3D 0; > + > + > + =A0if (libthread_db_search_path =3D=3D NULL) > + =A0 =A0libthread_db_search_path =3D xstrdup (LIBTHREAD_DB_SEARCH_PATH); > + > + =A0search_path =3D libthread_db_search_path; > + =A0while (*search_path) > + =A0 =A0{ > + =A0 =A0 =A0const char *end =3D strchr (search_path, ':'); > + =A0 =A0 =A0if (end) > +=A0=A0=A0=A0=A0=A0=A0{ > +=A0=A0=A0=A0=A0=A0=A0 =A0size_t len =3D end - search_path; > + =A0 =A0 =A0 =A0 =A0if (len + 1 + strlen (LIBTHREAD_DB_SO) + 1 > sizeof = (path)) > + =A0 =A0 =A0 =A0 =A0 =A0{ > + =A0 =A0 =A0 =A0 =A0 =A0 =A0char *cp =3D xmalloc (len + 1); > + =A0 =A0 =A0 =A0 =A0 =A0 =A0memcpy (cp, search_path, len); > + =A0 =A0 =A0 =A0 =A0 =A0 =A0cp[len] =3D '\0'; > + =A0 =A0 =A0 =A0 =A0 =A0 =A0warning ("libthread_db_search_path component= too long, " > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 =A0 =A0 =A0 "ignored: %s."= , cp); > + =A0 =A0 =A0 =A0 =A0 =A0 =A0free (cp); > + =A0 =A0 =A0 =A0 =A0 =A0 =A0search_path +=3D len + 1; > + =A0 =A0 =A0 =A0 =A0 =A0 =A0continue; > + =A0 =A0 =A0 =A0 =A0 =A0} > +=A0=A0=A0=A0=A0=A0=A0 =A0memcpy (path, search_path, len); > +=A0=A0=A0=A0=A0=A0=A0 =A0path[len] =3D '\0'; > +=A0=A0=A0=A0=A0=A0=A0 =A0search_path +=3D len + 1; > +=A0=A0=A0=A0=A0=A0=A0} > + =A0 =A0 =A0else > +=A0=A0=A0=A0=A0=A0=A0{ > + =A0 =A0 =A0 =A0 =A0size_t len =3D strlen (search_path); > + > + =A0 =A0 =A0 =A0 =A0if (len + 1 + strlen (LIBTHREAD_DB_SO) + 1 > sizeof = (path)) > + =A0 =A0 =A0 =A0 =A0 =A0{ > +=A0=A0=A0=A0=A0=A0=A0 =A0 =A0 =A0warning ("libthread_db_search_path comp= onent too long," > +=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0=A0 =A0 =A0 =A0 " ignored: %s.= ", search_path); > + =A0 =A0 =A0 =A0 =A0 =A0 =A0break; Something fishy with the alignment here? Mind tab vs spaces. > + =A0 =A0 =A0 =A0 =A0 =A0} > +=A0=A0=A0=A0=A0=A0=A0 =A0memcpy (path, search_path, len + 1); > +=A0=A0=A0=A0=A0=A0=A0 =A0search_path +=3D len; > +=A0=A0=A0=A0=A0=A0=A0} > + =A0 =A0 =A0strcat (path, "/"); > + =A0 =A0 =A0strcat (path, LIBTHREAD_DB_SO); > + =A0 =A0 =A0if (debug_threads) > + =A0 =A0 =A0 =A0fprintf (stderr, "thread_db_load_search trying %s\n", pa= th); > + =A0 =A0 =A0if (try_thread_db_load (path)) > +=A0=A0=A0=A0=A0=A0=A0{ > +=A0=A0=A0=A0=A0=A0=A0 =A0rc =3D 1; > +=A0=A0=A0=A0=A0=A0=A0 =A0break; > +=A0=A0=A0=A0=A0=A0=A0} > + =A0 =A0} > + =A0if (rc =3D=3D 0) > + =A0 =A0rc =3D try_thread_db_load (LIBTHREAD_DB_SO); > + > + =A0if (debug_threads) > + =A0 =A0fprintf (stderr, "thread_db_load_search returning %d\n", rc); > + =A0return rc; > =A0} > =A0 --=20 Pedro Alves