finally move buildroot-ng to trunk
This commit is contained in:
		| @@ -0,0 +1,593 @@ | ||||
| Support loading two libthread_db DSOs.  In this case, the LinuxThreads | ||||
| and NPTL ones. | ||||
|  | ||||
| Index: gdb-6.3/gdb/thread-db.c | ||||
| =================================================================== | ||||
| --- gdb-6.3.orig/gdb/thread-db.c	2004-11-10 10:46:24.000000000 -0500 | ||||
| +++ gdb-6.3/gdb/thread-db.c	2004-11-10 11:22:34.858812426 -0500 | ||||
| @@ -79,53 +79,63 @@ static td_thragent_t *thread_agent; | ||||
|   | ||||
|  /* Pointers to the libthread_db functions.  */ | ||||
|   | ||||
| -static td_err_e (*td_init_p) (void); | ||||
| +struct thread_db_pointers | ||||
| +{ | ||||
| +  const char *filename; | ||||
| + | ||||
| +  td_err_e (*td_init_p) (void); | ||||
|   | ||||
| -static td_err_e (*td_ta_new_p) (struct ps_prochandle * ps, | ||||
| -				td_thragent_t **ta); | ||||
| -static td_err_e (*td_ta_map_id2thr_p) (const td_thragent_t *ta, thread_t pt, | ||||
| -				       td_thrhandle_t *__th); | ||||
| -static td_err_e (*td_ta_map_lwp2thr_p) (const td_thragent_t *ta, | ||||
| -					lwpid_t lwpid, td_thrhandle_t *th); | ||||
| -static td_err_e (*td_ta_thr_iter_p) (const td_thragent_t *ta, | ||||
| -				     td_thr_iter_f *callback, void *cbdata_p, | ||||
| -				     td_thr_state_e state, int ti_pri, | ||||
| -				     sigset_t *ti_sigmask_p, | ||||
| -				     unsigned int ti_user_flags); | ||||
| -static td_err_e (*td_ta_event_addr_p) (const td_thragent_t *ta, | ||||
| -				       td_event_e event, td_notify_t *ptr); | ||||
| -static td_err_e (*td_ta_set_event_p) (const td_thragent_t *ta, | ||||
| -				      td_thr_events_t *event); | ||||
| -static td_err_e (*td_ta_event_getmsg_p) (const td_thragent_t *ta, | ||||
| -					 td_event_msg_t *msg); | ||||
| - | ||||
| -static td_err_e (*td_thr_validate_p) (const td_thrhandle_t *th); | ||||
| -static td_err_e (*td_thr_get_info_p) (const td_thrhandle_t *th, | ||||
| -				      td_thrinfo_t *infop); | ||||
| -static td_err_e (*td_thr_getfpregs_p) (const td_thrhandle_t *th, | ||||
| -				       gdb_prfpregset_t *regset); | ||||
| -static td_err_e (*td_thr_getgregs_p) (const td_thrhandle_t *th, | ||||
| -				      prgregset_t gregs); | ||||
| -static td_err_e (*td_thr_setfpregs_p) (const td_thrhandle_t *th, | ||||
| -				       const gdb_prfpregset_t *fpregs); | ||||
| -static td_err_e (*td_thr_setgregs_p) (const td_thrhandle_t *th, | ||||
| -				      prgregset_t gregs); | ||||
| -static td_err_e (*td_thr_event_enable_p) (const td_thrhandle_t *th, | ||||
| -					  int event); | ||||
| - | ||||
| -static td_err_e (*td_thr_tls_get_addr_p) (const td_thrhandle_t *th, | ||||
| -					  void *map_address, | ||||
| -					  size_t offset, void **address); | ||||
| +  td_err_e (*td_ta_new_p) (struct ps_prochandle * ps, | ||||
| +			   td_thragent_t **ta); | ||||
| +  td_err_e (*td_ta_map_id2thr_p) (const td_thragent_t *ta, thread_t pt, | ||||
| +				  td_thrhandle_t *__th); | ||||
| +  td_err_e (*td_ta_map_lwp2thr_p) (const td_thragent_t *ta, | ||||
| +				   lwpid_t lwpid, td_thrhandle_t *th); | ||||
| + | ||||
| +  td_err_e (*td_ta_thr_iter_p) (const td_thragent_t *ta, | ||||
| +				td_thr_iter_f *callback, void *cbdata_p, | ||||
| +				td_thr_state_e state, int ti_pri, | ||||
| +				sigset_t *ti_sigmask_p, | ||||
| +				unsigned int ti_user_flags); | ||||
| +  td_err_e (*td_ta_event_addr_p) (const td_thragent_t *ta, | ||||
| +				  td_event_e event, td_notify_t *ptr); | ||||
| +  td_err_e (*td_ta_set_event_p) (const td_thragent_t *ta, | ||||
| +				 td_thr_events_t *event); | ||||
| +  td_err_e (*td_ta_event_getmsg_p) (const td_thragent_t *ta, | ||||
| +				    td_event_msg_t *msg); | ||||
| + | ||||
| +  td_err_e (*td_thr_validate_p) (const td_thrhandle_t *th); | ||||
| +  td_err_e (*td_thr_get_info_p) (const td_thrhandle_t *th, | ||||
| +				 td_thrinfo_t *infop); | ||||
| +  td_err_e (*td_thr_getfpregs_p) (const td_thrhandle_t *th, | ||||
| +				  gdb_prfpregset_t *regset); | ||||
| +  td_err_e (*td_thr_getgregs_p) (const td_thrhandle_t *th, | ||||
| +				 prgregset_t gregs); | ||||
| +  td_err_e (*td_thr_setfpregs_p) (const td_thrhandle_t *th, | ||||
| +				  const gdb_prfpregset_t *fpregs); | ||||
| +  td_err_e (*td_thr_setgregs_p) (const td_thrhandle_t *th, | ||||
| +				 prgregset_t gregs); | ||||
| +  td_err_e (*td_thr_event_enable_p) (const td_thrhandle_t *th, | ||||
| +				     int event); | ||||
| + | ||||
| +  td_err_e (*td_thr_tls_get_addr_p) (const td_thrhandle_t *th, | ||||
| +				     void *map_address, | ||||
| +				     size_t offset, void **address); | ||||
| + | ||||
| +  struct thread_db_pointers *next; | ||||
| +}; | ||||
|   | ||||
|  /* Location of the thread creation event breakpoint.  The code at this | ||||
|     location in the child process will be called by the pthread library | ||||
|     whenever a new thread is created.  By setting a special breakpoint | ||||
|     at this location, GDB can detect when a new thread is created.  We | ||||
|     obtain this location via the td_ta_event_addr call.  */ | ||||
| -static CORE_ADDR td_create_bp_addr; | ||||
| +CORE_ADDR td_create_bp_addr; | ||||
|   | ||||
|  /* Location of the thread death event breakpoint.  */ | ||||
| -static CORE_ADDR td_death_bp_addr; | ||||
| +CORE_ADDR td_death_bp_addr; | ||||
| + | ||||
| +static struct thread_db_pointers *current_pointers, *all_pointers; | ||||
|   | ||||
|  /* Prototypes for local functions.  */ | ||||
|  static void thread_db_find_new_threads (void); | ||||
| @@ -262,7 +272,7 @@ thread_get_info_callback (const td_thrha | ||||
|    struct thread_info *thread_info; | ||||
|    ptid_t thread_ptid; | ||||
|   | ||||
| -  err = td_thr_get_info_p (thp, &ti); | ||||
| +  err = current_pointers->td_thr_get_info_p (thp, &ti); | ||||
|    if (err != TD_OK) | ||||
|      error ("thread_get_info_callback: cannot get thread info: %s", | ||||
|  	   thread_db_err_str (err)); | ||||
| @@ -316,8 +326,9 @@ thread_db_map_id2thr (struct thread_info | ||||
|    if (thread_info->private->th_valid) | ||||
|      return; | ||||
|   | ||||
| -  err = td_ta_map_id2thr_p (thread_agent, GET_THREAD (thread_info->ptid), | ||||
| -			    &thread_info->private->th); | ||||
| +  err = current_pointers->td_ta_map_id2thr_p (thread_agent, | ||||
| +					      GET_THREAD (thread_info->ptid), | ||||
| +					      &thread_info->private->th); | ||||
|    if (err != TD_OK) | ||||
|      { | ||||
|        if (fatal) | ||||
| @@ -340,8 +351,8 @@ thread_db_get_info (struct thread_info * | ||||
|    if (!thread_info->private->th_valid) | ||||
|      thread_db_map_id2thr (thread_info, 1); | ||||
|   | ||||
| -  err = | ||||
| -    td_thr_get_info_p (&thread_info->private->th, &thread_info->private->ti); | ||||
| +  err = current_pointers->td_thr_get_info_p (&thread_info->private->th, | ||||
| +					     &thread_info->private->ti); | ||||
|    if (err != TD_OK) | ||||
|      error ("thread_db_get_info: cannot get thread info: %s", | ||||
|  	   thread_db_err_str (err)); | ||||
| @@ -365,7 +376,8 @@ thread_from_lwp (ptid_t ptid) | ||||
|   | ||||
|    gdb_assert (is_lwp (ptid)); | ||||
|   | ||||
| -  err = td_ta_map_lwp2thr_p (thread_agent, GET_LWP (ptid), &th); | ||||
| +  err = current_pointers->td_ta_map_lwp2thr_p (thread_agent, GET_LWP (ptid), | ||||
| +					       &th); | ||||
|    if (err != TD_OK) | ||||
|      error ("Cannot find user-level thread for LWP %ld: %s", | ||||
|  	   GET_LWP (ptid), thread_db_err_str (err)); | ||||
| @@ -420,85 +432,102 @@ verbose_dlsym (void *handle, const char  | ||||
|    return sym; | ||||
|  } | ||||
|   | ||||
| -static int | ||||
| -thread_db_load (void) | ||||
| +static struct thread_db_pointers * | ||||
| +thread_db_load (const char *name) | ||||
|  { | ||||
| +  struct thread_db_pointers *ptrs; | ||||
| +  Dl_info info; | ||||
|    void *handle; | ||||
|    td_err_e err; | ||||
|   | ||||
| -  handle = dlopen (LIBTHREAD_DB_SO, RTLD_NOW); | ||||
| +  ptrs = xcalloc (1, sizeof (struct thread_db_pointers)); | ||||
| + | ||||
| +  handle = dlopen (name, RTLD_NOW); | ||||
|    if (handle == NULL) | ||||
|      { | ||||
| -      fprintf_filtered (gdb_stderr, "\n\ndlopen failed on '%s' - %s\n", | ||||
| -			LIBTHREAD_DB_SO, dlerror ()); | ||||
| -      fprintf_filtered (gdb_stderr, | ||||
| -			"GDB will not be able to debug pthreads.\n\n"); | ||||
| +      if (all_pointers == NULL) | ||||
| +	{ | ||||
| +	  fprintf_filtered (gdb_stderr, "\n\ndlopen failed on '%s' - %s\n", | ||||
| +			    name, dlerror ()); | ||||
| +	  fprintf_filtered (gdb_stderr, | ||||
| +			    "GDB will not be able to debug pthreads.\n\n"); | ||||
| +	} | ||||
|        return 0; | ||||
|      } | ||||
|   | ||||
|    /* Initialize pointers to the dynamic library functions we will use. | ||||
|       Essential functions first.  */ | ||||
|   | ||||
| -  td_init_p = verbose_dlsym (handle, "td_init"); | ||||
| -  if (td_init_p == NULL) | ||||
| +  ptrs->td_init_p = verbose_dlsym (handle, "td_init"); | ||||
| +  if (ptrs->td_init_p == NULL) | ||||
|      return 0; | ||||
|   | ||||
| -  td_ta_new_p = verbose_dlsym (handle, "td_ta_new"); | ||||
| -  if (td_ta_new_p == NULL) | ||||
| +  ptrs->td_ta_new_p = verbose_dlsym (handle, "td_ta_new"); | ||||
| +  if (ptrs->td_ta_new_p == NULL) | ||||
|      return 0; | ||||
|   | ||||
| -  td_ta_map_id2thr_p = verbose_dlsym (handle, "td_ta_map_id2thr"); | ||||
| -  if (td_ta_map_id2thr_p == NULL) | ||||
| +  ptrs->td_ta_map_id2thr_p = verbose_dlsym (handle, "td_ta_map_id2thr"); | ||||
| +  if (ptrs->td_ta_map_id2thr_p == NULL) | ||||
|      return 0; | ||||
|   | ||||
| -  td_ta_map_lwp2thr_p = verbose_dlsym (handle, "td_ta_map_lwp2thr"); | ||||
| -  if (td_ta_map_lwp2thr_p == NULL) | ||||
| +  ptrs->td_ta_map_lwp2thr_p = verbose_dlsym (handle, "td_ta_map_lwp2thr"); | ||||
| +  if (ptrs->td_ta_map_lwp2thr_p == NULL) | ||||
|      return 0; | ||||
|   | ||||
| -  td_ta_thr_iter_p = verbose_dlsym (handle, "td_ta_thr_iter"); | ||||
| -  if (td_ta_thr_iter_p == NULL) | ||||
| +  ptrs->td_ta_thr_iter_p = verbose_dlsym (handle, "td_ta_thr_iter"); | ||||
| +  if (ptrs->td_ta_thr_iter_p == NULL) | ||||
|      return 0; | ||||
|   | ||||
| -  td_thr_validate_p = verbose_dlsym (handle, "td_thr_validate"); | ||||
| -  if (td_thr_validate_p == NULL) | ||||
| +  ptrs->td_thr_validate_p = verbose_dlsym (handle, "td_thr_validate"); | ||||
| +  if (ptrs->td_thr_validate_p == NULL) | ||||
|      return 0; | ||||
|   | ||||
| -  td_thr_get_info_p = verbose_dlsym (handle, "td_thr_get_info"); | ||||
| -  if (td_thr_get_info_p == NULL) | ||||
| +  ptrs->td_thr_get_info_p = verbose_dlsym (handle, "td_thr_get_info"); | ||||
| +  if (ptrs->td_thr_get_info_p == NULL) | ||||
|      return 0; | ||||
|   | ||||
| -  td_thr_getfpregs_p = verbose_dlsym (handle, "td_thr_getfpregs"); | ||||
| -  if (td_thr_getfpregs_p == NULL) | ||||
| +  ptrs->td_thr_getfpregs_p = verbose_dlsym (handle, "td_thr_getfpregs"); | ||||
| +  if (ptrs->td_thr_getfpregs_p == NULL) | ||||
|      return 0; | ||||
|   | ||||
| -  td_thr_getgregs_p = verbose_dlsym (handle, "td_thr_getgregs"); | ||||
| -  if (td_thr_getgregs_p == NULL) | ||||
| +  ptrs->td_thr_getgregs_p = verbose_dlsym (handle, "td_thr_getgregs"); | ||||
| +  if (ptrs->td_thr_getgregs_p == NULL) | ||||
|      return 0; | ||||
|   | ||||
| -  td_thr_setfpregs_p = verbose_dlsym (handle, "td_thr_setfpregs"); | ||||
| -  if (td_thr_setfpregs_p == NULL) | ||||
| +  ptrs->td_thr_setfpregs_p = verbose_dlsym (handle, "td_thr_setfpregs"); | ||||
| +  if (ptrs->td_thr_setfpregs_p == NULL) | ||||
|      return 0; | ||||
|   | ||||
| -  td_thr_setgregs_p = verbose_dlsym (handle, "td_thr_setgregs"); | ||||
| -  if (td_thr_setgregs_p == NULL) | ||||
| +  ptrs->td_thr_setgregs_p = verbose_dlsym (handle, "td_thr_setgregs"); | ||||
| +  if (ptrs->td_thr_setgregs_p == NULL) | ||||
|      return 0; | ||||
|   | ||||
|    /* Initialize the library.  */ | ||||
| -  err = td_init_p (); | ||||
| +  err = ptrs->td_init_p (); | ||||
|    if (err != TD_OK) | ||||
|      { | ||||
|        warning ("Cannot initialize libthread_db: %s", thread_db_err_str (err)); | ||||
| +      xfree (ptrs); | ||||
|        return 0; | ||||
|      } | ||||
|   | ||||
|    /* These are not essential.  */ | ||||
| -  td_ta_event_addr_p = dlsym (handle, "td_ta_event_addr"); | ||||
| -  td_ta_set_event_p = dlsym (handle, "td_ta_set_event"); | ||||
| -  td_ta_event_getmsg_p = dlsym (handle, "td_ta_event_getmsg"); | ||||
| -  td_thr_event_enable_p = dlsym (handle, "td_thr_event_enable"); | ||||
| -  td_thr_tls_get_addr_p = dlsym (handle, "td_thr_tls_get_addr"); | ||||
| +  ptrs->td_ta_event_addr_p = dlsym (handle, "td_ta_event_addr"); | ||||
| +  ptrs->td_ta_set_event_p = dlsym (handle, "td_ta_set_event"); | ||||
| +  ptrs->td_ta_event_getmsg_p = dlsym (handle, "td_ta_event_getmsg"); | ||||
| +  ptrs->td_thr_event_enable_p = dlsym (handle, "td_thr_event_enable"); | ||||
| +  ptrs->td_thr_tls_get_addr_p = dlsym (handle, "td_thr_tls_get_addr"); | ||||
| + | ||||
| +  if (dladdr (ptrs->td_ta_new_p, &info) != 0) | ||||
| +    ptrs->filename = info.dli_fname; | ||||
| + | ||||
| +  /* Try dlinfo?  */ | ||||
| + | ||||
| +  if (ptrs->filename == NULL) | ||||
| +    /* Paranoid - don't let a NULL path slip through.  */ | ||||
| +    ptrs->filename = name; | ||||
|   | ||||
| -  return 1; | ||||
| +  return ptrs; | ||||
|  } | ||||
|   | ||||
|  static td_err_e | ||||
| @@ -508,7 +537,7 @@ enable_thread_event (td_thragent_t *thre | ||||
|    td_err_e err; | ||||
|   | ||||
|    /* Get the breakpoint address for thread EVENT.  */ | ||||
| -  err = td_ta_event_addr_p (thread_agent, event, ¬ify); | ||||
| +  err = current_pointers->td_ta_event_addr_p (thread_agent, event, ¬ify); | ||||
|    if (err != TD_OK) | ||||
|      return err; | ||||
|   | ||||
| @@ -534,8 +563,10 @@ enable_thread_event_reporting (void) | ||||
|   | ||||
|    /* We cannot use the thread event reporting facility if these | ||||
|       functions aren't available.  */ | ||||
| -  if (td_ta_event_addr_p == NULL || td_ta_set_event_p == NULL | ||||
| -      || td_ta_event_getmsg_p == NULL || td_thr_event_enable_p == NULL) | ||||
| +  if (current_pointers->td_ta_event_addr_p == NULL | ||||
| +      || current_pointers->td_ta_set_event_p == NULL | ||||
| +      || current_pointers->td_ta_event_getmsg_p == NULL | ||||
| +      || current_pointers->td_thr_event_enable_p == NULL) | ||||
|      return; | ||||
|   | ||||
|    /* Set the process wide mask saying which events we're interested in.  */ | ||||
| @@ -552,7 +583,7 @@ enable_thread_event_reporting (void) | ||||
|  #endif | ||||
|      td_event_addset (&events, TD_DEATH); | ||||
|   | ||||
| -  err = td_ta_set_event_p (thread_agent, &events); | ||||
| +  err = current_pointers->td_ta_set_event_p (thread_agent, &events); | ||||
|    if (err != TD_OK) | ||||
|      { | ||||
|        warning ("Unable to set global thread event mask: %s", | ||||
| @@ -592,7 +623,7 @@ disable_thread_event_reporting (void) | ||||
|    /* Set the process wide mask saying we aren't interested in any | ||||
|       events anymore.  */ | ||||
|    td_event_emptyset (&events); | ||||
| -  td_ta_set_event_p (thread_agent, &events); | ||||
| +  current_pointers->td_ta_set_event_p (thread_agent, &events); | ||||
|   | ||||
|    /* Delete thread event breakpoints, if any.  */ | ||||
|    remove_thread_event_breakpoints (); | ||||
| @@ -635,7 +666,6 @@ check_thread_signals (void) | ||||
|  static void | ||||
|  check_for_thread_db (void) | ||||
|  { | ||||
| -  td_err_e err; | ||||
|    static int already_loaded; | ||||
|   | ||||
|    /* First time through, report that libthread_db was successfuly | ||||
| @@ -644,19 +674,8 @@ check_for_thread_db (void) | ||||
|   | ||||
|    if (!already_loaded) | ||||
|      { | ||||
| -      Dl_info info; | ||||
| -      const char *library = NULL; | ||||
| -      if (dladdr ((*td_ta_new_p), &info) != 0) | ||||
| -	library = info.dli_fname; | ||||
| - | ||||
| -      /* Try dlinfo?  */ | ||||
| - | ||||
| -      if (library == NULL) | ||||
| -	/* Paranoid - don't let a NULL path slip through.  */ | ||||
| -	library = LIBTHREAD_DB_SO; | ||||
| - | ||||
|        printf_unfiltered ("Using host libthread_db library \"%s\".\n", | ||||
| -			 library); | ||||
| +			 all_pointers->filename); | ||||
|        already_loaded = 1; | ||||
|      } | ||||
|   | ||||
| @@ -674,28 +693,34 @@ check_for_thread_db (void) | ||||
|    proc_handle.pid = GET_PID (inferior_ptid); | ||||
|   | ||||
|    /* Now attempt to open a connection to the thread library.  */ | ||||
| -  err = td_ta_new_p (&proc_handle, &thread_agent); | ||||
| -  switch (err) | ||||
| +  for (current_pointers = all_pointers; | ||||
| +       current_pointers != NULL; | ||||
| +       current_pointers = current_pointers->next) | ||||
|      { | ||||
| -    case TD_NOLIBTHREAD: | ||||
| -      /* No thread library was detected.  */ | ||||
| -      break; | ||||
| - | ||||
| -    case TD_OK: | ||||
| -      printf_unfiltered ("[Thread debugging using libthread_db enabled]\n"); | ||||
| +      td_err_e err; | ||||
| +      err = current_pointers->td_ta_new_p (&proc_handle, &thread_agent); | ||||
| +      switch (err) | ||||
| +	{ | ||||
| +	case TD_NOLIBTHREAD: | ||||
| +	  /* No thread library was detected.  */ | ||||
| +	  break; | ||||
|   | ||||
| -      /* The thread library was detected.  Activate the thread_db target.  */ | ||||
| -      push_target (&thread_db_ops); | ||||
| -      using_thread_db = 1; | ||||
| +	case TD_OK: | ||||
| +	  printf_unfiltered ("[Thread debugging using libthread_db enabled]\n"); | ||||
|   | ||||
| -      enable_thread_event_reporting (); | ||||
| -      thread_db_find_new_threads (); | ||||
| -      break; | ||||
| +	  /* The thread library was detected.  Activate the thread_db target.  */ | ||||
| +	  push_target (&thread_db_ops); | ||||
| +	  using_thread_db = 1; | ||||
| + | ||||
| +	  enable_thread_event_reporting (); | ||||
| +	  thread_db_find_new_threads (); | ||||
| +	  return; | ||||
|   | ||||
| -    default: | ||||
| -      warning ("Cannot initialize thread debugging library: %s", | ||||
| -	       thread_db_err_str (err)); | ||||
| -      break; | ||||
| +	default: | ||||
| +	  warning ("Cannot initialize thread debugging library: %s", | ||||
| +		   thread_db_err_str (err)); | ||||
| +	  break; | ||||
| +	} | ||||
|      } | ||||
|  } | ||||
|   | ||||
| @@ -766,7 +791,7 @@ attach_thread (ptid_t ptid, const td_thr | ||||
|  #endif | ||||
|   | ||||
|    /* Enable thread event reporting for this thread.  */ | ||||
| -  err = td_thr_event_enable_p (th_p, 1); | ||||
| +  err = current_pointers->td_thr_event_enable_p (th_p, 1); | ||||
|    if (err != TD_OK) | ||||
|      error ("Cannot enable thread event reporting for %s: %s", | ||||
|  	   target_pid_to_str (ptid), thread_db_err_str (err)); | ||||
| @@ -892,7 +917,7 @@ check_event (ptid_t ptid) | ||||
|   | ||||
|    do | ||||
|      { | ||||
| -      err = td_ta_event_getmsg_p (thread_agent, &msg); | ||||
| +      err = current_pointers->td_ta_event_getmsg_p (thread_agent, &msg); | ||||
|        if (err != TD_OK) | ||||
|  	{ | ||||
|  	  if (err == TD_NOMSG) | ||||
| @@ -902,7 +927,7 @@ check_event (ptid_t ptid) | ||||
|  		 thread_db_err_str (err)); | ||||
|  	} | ||||
|   | ||||
| -      err = td_thr_get_info_p (msg.th_p, &ti); | ||||
| +      err = current_pointers->td_thr_get_info_p (msg.th_p, &ti); | ||||
|        if (err != TD_OK) | ||||
|  	error ("Cannot get thread info: %s", thread_db_err_str (err)); | ||||
|   | ||||
| @@ -1015,12 +1040,14 @@ thread_db_fetch_registers (int regno) | ||||
|    thread_info = find_thread_pid (inferior_ptid); | ||||
|    thread_db_map_id2thr (thread_info, 1); | ||||
|   | ||||
| -  err = td_thr_getgregs_p (&thread_info->private->th, gregset); | ||||
| +  err = current_pointers->td_thr_getgregs_p (&thread_info->private->th, | ||||
| +					     gregset); | ||||
|    if (err != TD_OK) | ||||
|      error ("Cannot fetch general-purpose registers for thread %ld: %s", | ||||
|  	   (long) GET_THREAD (inferior_ptid), thread_db_err_str (err)); | ||||
|   | ||||
| -  err = td_thr_getfpregs_p (&thread_info->private->th, &fpregset); | ||||
| +  err = current_pointers->td_thr_getfpregs_p (&thread_info->private->th, | ||||
| +					      &fpregset); | ||||
|    if (err != TD_OK) | ||||
|      error ("Cannot get floating-point registers for thread %ld: %s", | ||||
|  	   (long) GET_THREAD (inferior_ptid), thread_db_err_str (err)); | ||||
| @@ -1062,11 +1089,13 @@ thread_db_store_registers (int regno) | ||||
|    fill_gregset ((gdb_gregset_t *) gregset, -1); | ||||
|    fill_fpregset (&fpregset, -1); | ||||
|   | ||||
| -  err = td_thr_setgregs_p (&thread_info->private->th, gregset); | ||||
| +  err = current_pointers->td_thr_setgregs_p (&thread_info->private->th, | ||||
| +					     gregset); | ||||
|    if (err != TD_OK) | ||||
|      error ("Cannot store general-purpose registers for thread %ld: %s", | ||||
|  	   (long) GET_THREAD (inferior_ptid), thread_db_err_str (err)); | ||||
| -  err = td_thr_setfpregs_p (&thread_info->private->th, &fpregset); | ||||
| +  err = current_pointers->td_thr_setfpregs_p (&thread_info->private->th, | ||||
| +					      &fpregset); | ||||
|    if (err != TD_OK) | ||||
|      error ("Cannot store floating-point registers  for thread %ld: %s", | ||||
|  	   (long) GET_THREAD (inferior_ptid), thread_db_err_str (err)); | ||||
| @@ -1136,15 +1165,14 @@ thread_db_thread_alive (ptid_t ptid) | ||||
|        if (!thread_info->private->th_valid) | ||||
|  	return 0; | ||||
|   | ||||
| -      err = td_thr_validate_p (&thread_info->private->th); | ||||
| +      err = current_pointers->td_thr_validate_p (&thread_info->private->th); | ||||
|        if (err != TD_OK) | ||||
|  	return 0; | ||||
|   | ||||
|        if (!thread_info->private->ti_valid) | ||||
|  	{ | ||||
| -	  err = | ||||
| -	    td_thr_get_info_p (&thread_info->private->th, | ||||
| -			       &thread_info->private->ti); | ||||
| +	  err = current_pointers->td_thr_get_info_p | ||||
| +	    (&thread_info->private->th, &thread_info->private->ti); | ||||
|  	  if (err != TD_OK) | ||||
|  	    return 0; | ||||
|  	  thread_info->private->ti_valid = 1; | ||||
| @@ -1170,7 +1198,7 @@ find_new_threads_callback (const td_thrh | ||||
|    td_err_e err; | ||||
|    ptid_t ptid; | ||||
|   | ||||
| -  err = td_thr_get_info_p (th_p, &ti); | ||||
| +  err = current_pointers->td_thr_get_info_p (th_p, &ti); | ||||
|    if (err != TD_OK) | ||||
|      error ("find_new_threads_callback: cannot get thread info: %s", | ||||
|  	   thread_db_err_str (err)); | ||||
| @@ -1192,9 +1220,10 @@ thread_db_find_new_threads (void) | ||||
|    td_err_e err; | ||||
|   | ||||
|    /* Iterate over all user-space threads to discover new threads.  */ | ||||
| -  err = td_ta_thr_iter_p (thread_agent, find_new_threads_callback, NULL, | ||||
| -			  TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY, | ||||
| -			  TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS); | ||||
| +  err = current_pointers->td_ta_thr_iter_p | ||||
| +    (thread_agent, find_new_threads_callback, NULL, | ||||
| +     TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY, | ||||
| +     TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS); | ||||
|    if (err != TD_OK) | ||||
|      error ("Cannot find new threads: %s", thread_db_err_str (err)); | ||||
|  } | ||||
| @@ -1257,7 +1286,7 @@ thread_db_get_thread_local_address (ptid | ||||
|        struct thread_info *thread_info; | ||||
|   | ||||
|        /* glibc doesn't provide the needed interface.  */ | ||||
| -      if (!td_thr_tls_get_addr_p) | ||||
| +      if (!current_pointers->td_thr_tls_get_addr_p) | ||||
|  	error ("Cannot find thread-local variables in this thread library."); | ||||
|   | ||||
|        /* Get the address of the link map for this objfile.  */ | ||||
| @@ -1279,8 +1308,8 @@ thread_db_get_thread_local_address (ptid | ||||
|        thread_db_map_id2thr (thread_info, 1); | ||||
|   | ||||
|        /* Finally, get the address of the variable.  */ | ||||
| -      err = td_thr_tls_get_addr_p (&thread_info->private->th, (void *) lm, | ||||
| -				   offset, &address); | ||||
| +      err = current_pointers->td_thr_tls_get_addr_p | ||||
| +	(&thread_info->private->th, (void *) lm, offset, &address); | ||||
|   | ||||
|  #ifdef THREAD_DB_HAS_TD_NOTALLOC | ||||
|        /* The memory hasn't been allocated, yet.  */ | ||||
| @@ -1360,17 +1389,49 @@ init_thread_db_ops (void) | ||||
|  void | ||||
|  _initialize_thread_db (void) | ||||
|  { | ||||
| +  struct thread_db_pointers *ptrs; | ||||
| +  const char *p; | ||||
| + | ||||
|    /* Only initialize the module if we can load libthread_db.  */ | ||||
| -  if (thread_db_load ()) | ||||
| -    { | ||||
| -      init_thread_db_ops (); | ||||
| -      add_target (&thread_db_ops); | ||||
| +  ptrs = thread_db_load (LIBTHREAD_DB_SO); | ||||
| +  if (ptrs == NULL) | ||||
| +    return; | ||||
| + | ||||
| +  all_pointers = ptrs; | ||||
|   | ||||
| -      /* Add ourselves to objfile event chain.  */ | ||||
| -      target_new_objfile_chain = deprecated_target_new_objfile_hook; | ||||
| -      deprecated_target_new_objfile_hook = thread_db_new_objfile; | ||||
| +  /* Some GNU/Linux systems have more than one binary-compatible copy | ||||
| +     of libthread_db.  If we can find a second one, load that too. | ||||
| +     The inferior may force the use of a different threading package | ||||
| +     than we expect.  Our guess for the location is somewhat hokey: | ||||
| +     strip out anything between /lib (or /lib64) and LIBTHREAD_DB_SO. | ||||
| +     If we loaded the NPTL libthread_db by default, this may find us | ||||
| +     the LinuxThreads copy.  */ | ||||
| +  p = strrchr (ptrs->filename, '/'); | ||||
| +  while (p != NULL && p > ptrs->filename) | ||||
| +    { | ||||
| +      const char *component; | ||||
|   | ||||
| -      /* Register ourselves for the new inferior observer.  */ | ||||
| -      observer_attach_inferior_created (check_for_thread_db_observer); | ||||
| +      component = memrchr (ptrs->filename, '/', p - ptrs->filename); | ||||
| +      if (component != NULL && strncmp (component, "/lib", 4) == 0) | ||||
| +	{ | ||||
| +	  char *new_name = xmalloc (p - ptrs->filename + 2 | ||||
| +				    + strlen (LIBTHREAD_DB_SO)); | ||||
| +	  memcpy (new_name, ptrs->filename, p - ptrs->filename + 1); | ||||
| +	  strcpy (new_name + (p - ptrs->filename) + 1, LIBTHREAD_DB_SO); | ||||
| +	  ptrs->next = thread_db_load (new_name); | ||||
| +	  xfree (new_name); | ||||
| +	  break; | ||||
| +	} | ||||
| +      p = component; | ||||
|      } | ||||
| + | ||||
| +  init_thread_db_ops (); | ||||
| +  add_target (&thread_db_ops); | ||||
| + | ||||
| +  /* Add ourselves to objfile event chain.  */ | ||||
| +  target_new_objfile_chain = deprecated_target_new_objfile_hook; | ||||
| +  deprecated_target_new_objfile_hook = thread_db_new_objfile; | ||||
| + | ||||
| +  /* Register ourselves for the new inferior observer.  */ | ||||
| +  observer_attach_inferior_created (check_for_thread_db_observer); | ||||
|  } | ||||
		Reference in New Issue
	
	Block a user
	 Felix Fietkau
					Felix Fietkau