1 /* Solaris threads debugging interface. 2 3 Copyright (C) 1996-2017 Free Software Foundation, Inc. 4 5 This file is part of GDB. 6 7 This program is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 3 of the License, or 10 (at your option) any later version. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 19 20 /* This module implements a sort of half target that sits between the 21 machine-independent parts of GDB and the /proc interface (procfs.c) 22 to provide access to the Solaris user-mode thread implementation. 23 24 Solaris threads are true user-mode threads, which are invoked via 25 the thr_* and pthread_* (native and POSIX respectivly) interfaces. 26 These are mostly implemented in user-space, with all thread context 27 kept in various structures that live in the user's heap. These 28 should not be confused with lightweight processes (LWPs), which are 29 implemented by the kernel, and scheduled without explicit 30 intervention by the process. 31 32 Just to confuse things a little, Solaris threads (both native and 33 POSIX) are actually implemented using LWPs. In general, there are 34 going to be more threads than LWPs. There is no fixed 35 correspondence between a thread and an LWP. When a thread wants to 36 run, it gets scheduled onto the first available LWP and can 37 therefore migrate from one LWP to another as time goes on. A 38 sleeping thread may not be associated with an LWP at all! 39 40 To make it possible to mess with threads, Sun provides a library 41 called libthread_db.so.1 (not to be confused with 42 libthread_db.so.0, which doesn't have a published interface). This 43 interface has an upper part, which it provides, and a lower part 44 which we provide. The upper part consists of the td_* routines, 45 which allow us to find all the threads, query their state, etc... 46 The lower part consists of all of the ps_*, which are used by the 47 td_* routines to read/write memory, manipulate LWPs, lookup 48 symbols, etc... The ps_* routines actually do most of their work 49 by calling functions in procfs.c. */ 50 51 #include "defs.h" 52 #include <thread.h> 53 #include <proc_service.h> 54 #include <thread_db.h> 55 #include "gdbthread.h" 56 #include "target.h" 57 #include "inferior.h" 58 #include <fcntl.h> 59 #include <sys/stat.h> 60 #include <dlfcn.h> 61 #include "gdbcmd.h" 62 #include "gdbcore.h" 63 #include "regcache.h" 64 #include "solib.h" 65 #include "symfile.h" 66 #include "observer.h" 67 #include "procfs.h" 68 #include "symtab.h" 69 #include "minsyms.h" 70 #include "objfiles.h" 71 72 struct target_ops sol_thread_ops; 73 74 /* Prototypes for supply_gregset etc. */ 75 #include "gregset.h" 76 77 /* This struct is defined by us, but mainly used for the proc_service 78 interface. We don't have much use for it, except as a handy place 79 to get a real PID for memory accesses. */ 80 81 struct ps_prochandle 82 { 83 ptid_t ptid; 84 }; 85 86 struct string_map 87 { 88 int num; 89 const char *str; 90 }; 91 92 static struct ps_prochandle main_ph; 93 static td_thragent_t *main_ta; 94 static int sol_thread_active = 0; 95 96 static void init_sol_thread_ops (void); 97 98 /* Default definitions: These must be defined in tm.h if they are to 99 be shared with a process module such as procfs. */ 100 101 /* Types of the libthread_db functions. */ 102 103 typedef void (td_log_ftype)(const int on_off); 104 typedef td_err_e (td_ta_new_ftype)(const struct ps_prochandle *ph_p, 105 td_thragent_t **ta_pp); 106 typedef td_err_e (td_ta_delete_ftype)(td_thragent_t *ta_p); 107 typedef td_err_e (td_init_ftype)(void); 108 typedef td_err_e (td_ta_get_ph_ftype)(const td_thragent_t *ta_p, 109 struct ps_prochandle **ph_pp); 110 typedef td_err_e (td_ta_get_nthreads_ftype)(const td_thragent_t *ta_p, 111 int *nthread_p); 112 typedef td_err_e (td_ta_tsd_iter_ftype)(const td_thragent_t *ta_p, 113 td_key_iter_f *cb, void *cbdata_p); 114 typedef td_err_e (td_ta_thr_iter_ftype)(const td_thragent_t *ta_p, 115 td_thr_iter_f *cb, void *cbdata_p, 116 td_thr_state_e state, int ti_pri, 117 sigset_t *ti_sigmask_p, 118 unsigned ti_user_flags); 119 typedef td_err_e (td_thr_validate_ftype)(const td_thrhandle_t *th_p); 120 typedef td_err_e (td_thr_tsd_ftype)(const td_thrhandle_t * th_p, 121 const thread_key_t key, void **data_pp); 122 typedef td_err_e (td_thr_get_info_ftype)(const td_thrhandle_t *th_p, 123 td_thrinfo_t *ti_p); 124 typedef td_err_e (td_thr_getfpregs_ftype)(const td_thrhandle_t *th_p, 125 prfpregset_t *fpregset); 126 typedef td_err_e (td_thr_getxregsize_ftype)(const td_thrhandle_t *th_p, 127 int *xregsize); 128 typedef td_err_e (td_thr_getxregs_ftype)(const td_thrhandle_t *th_p, 129 const caddr_t xregset); 130 typedef td_err_e (td_thr_sigsetmask_ftype)(const td_thrhandle_t *th_p, 131 const sigset_t ti_sigmask); 132 typedef td_err_e (td_thr_setprio_ftype)(const td_thrhandle_t *th_p, 133 const int ti_pri); 134 typedef td_err_e (td_thr_setsigpending_ftype)(const td_thrhandle_t *th_p, 135 const uchar_t ti_pending_flag, 136 const sigset_t ti_pending); 137 typedef td_err_e (td_thr_setfpregs_ftype)(const td_thrhandle_t *th_p, 138 const prfpregset_t *fpregset); 139 typedef td_err_e (td_thr_setxregs_ftype)(const td_thrhandle_t *th_p, 140 const caddr_t xregset); 141 typedef td_err_e (td_ta_map_id2thr_ftype)(const td_thragent_t *ta_p, 142 thread_t tid, 143 td_thrhandle_t *th_p); 144 typedef td_err_e (td_ta_map_lwp2thr_ftype)(const td_thragent_t *ta_p, 145 lwpid_t lwpid, 146 td_thrhandle_t *th_p); 147 typedef td_err_e (td_thr_getgregs_ftype)(const td_thrhandle_t *th_p, 148 prgregset_t regset); 149 typedef td_err_e (td_thr_setgregs_ftype)(const td_thrhandle_t *th_p, 150 const prgregset_t regset); 151 152 /* Pointers to routines from libthread_db resolved by dlopen(). */ 153 154 static td_log_ftype *p_td_log; 155 static td_ta_new_ftype *p_td_ta_new; 156 static td_ta_delete_ftype *p_td_ta_delete; 157 static td_init_ftype *p_td_init; 158 static td_ta_get_ph_ftype *p_td_ta_get_ph; 159 static td_ta_get_nthreads_ftype *p_td_ta_get_nthreads; 160 static td_ta_tsd_iter_ftype *p_td_ta_tsd_iter; 161 static td_ta_thr_iter_ftype *p_td_ta_thr_iter; 162 static td_thr_validate_ftype *p_td_thr_validate; 163 static td_thr_tsd_ftype *p_td_thr_tsd; 164 static td_thr_get_info_ftype *p_td_thr_get_info; 165 static td_thr_getfpregs_ftype *p_td_thr_getfpregs; 166 static td_thr_getxregsize_ftype *p_td_thr_getxregsize; 167 static td_thr_getxregs_ftype *p_td_thr_getxregs; 168 static td_thr_sigsetmask_ftype *p_td_thr_sigsetmask; 169 static td_thr_setprio_ftype *p_td_thr_setprio; 170 static td_thr_setsigpending_ftype *p_td_thr_setsigpending; 171 static td_thr_setfpregs_ftype *p_td_thr_setfpregs; 172 static td_thr_setxregs_ftype *p_td_thr_setxregs; 173 static td_ta_map_id2thr_ftype *p_td_ta_map_id2thr; 174 static td_ta_map_lwp2thr_ftype *p_td_ta_map_lwp2thr; 175 static td_thr_getgregs_ftype *p_td_thr_getgregs; 176 static td_thr_setgregs_ftype *p_td_thr_setgregs; 177 178 179 /* Return the libthread_db error string associated with ERRCODE. If 180 ERRCODE is unknown, return an appropriate message. */ 181 182 static const char * 183 td_err_string (td_err_e errcode) 184 { 185 static struct string_map td_err_table[] = 186 { 187 { TD_OK, "generic \"call succeeded\"" }, 188 { TD_ERR, "generic error." }, 189 { TD_NOTHR, "no thread can be found to satisfy query" }, 190 { TD_NOSV, "no synch. variable can be found to satisfy query" }, 191 { TD_NOLWP, "no lwp can be found to satisfy query" }, 192 { TD_BADPH, "invalid process handle" }, 193 { TD_BADTH, "invalid thread handle" }, 194 { TD_BADSH, "invalid synchronization handle" }, 195 { TD_BADTA, "invalid thread agent" }, 196 { TD_BADKEY, "invalid key" }, 197 { TD_NOMSG, "td_thr_event_getmsg() called when there was no message" }, 198 { TD_NOFPREGS, "FPU register set not available for given thread" }, 199 { TD_NOLIBTHREAD, "application not linked with libthread" }, 200 { TD_NOEVENT, "requested event is not supported" }, 201 { TD_NOCAPAB, "capability not available" }, 202 { TD_DBERR, "Debugger service failed" }, 203 { TD_NOAPLIC, "Operation not applicable to" }, 204 { TD_NOTSD, "No thread specific data for this thread" }, 205 { TD_MALLOC, "Malloc failed" }, 206 { TD_PARTIALREG, "Only part of register set was written/read" }, 207 { TD_NOXREGS, "X register set not available for given thread" } 208 }; 209 const int td_err_size = sizeof td_err_table / sizeof (struct string_map); 210 int i; 211 static char buf[50]; 212 213 for (i = 0; i < td_err_size; i++) 214 if (td_err_table[i].num == errcode) 215 return td_err_table[i].str; 216 217 xsnprintf (buf, sizeof (buf), "Unknown libthread_db error code: %d", 218 errcode); 219 220 return buf; 221 } 222 223 /* Return the libthread_db state string assicoated with STATECODE. 224 If STATECODE is unknown, return an appropriate message. */ 225 226 static const char * 227 td_state_string (td_thr_state_e statecode) 228 { 229 static struct string_map td_thr_state_table[] = 230 { 231 { TD_THR_ANY_STATE, "any state" }, 232 { TD_THR_UNKNOWN, "unknown" }, 233 { TD_THR_STOPPED, "stopped" }, 234 { TD_THR_RUN, "run" }, 235 { TD_THR_ACTIVE, "active" }, 236 { TD_THR_ZOMBIE, "zombie" }, 237 { TD_THR_SLEEP, "sleep" }, 238 { TD_THR_STOPPED_ASLEEP, "stopped asleep" } 239 }; 240 const int td_thr_state_table_size = 241 sizeof td_thr_state_table / sizeof (struct string_map); 242 int i; 243 static char buf[50]; 244 245 for (i = 0; i < td_thr_state_table_size; i++) 246 if (td_thr_state_table[i].num == statecode) 247 return td_thr_state_table[i].str; 248 249 xsnprintf (buf, sizeof (buf), "Unknown libthread_db state code: %d", 250 statecode); 251 252 return buf; 253 } 254 255 256 /* Convert a POSIX or Solaris thread ID into a LWP ID. If THREAD_ID 257 doesn't exist, that's an error. If it's an inactive thread, return 258 DEFAULT_LWP. 259 260 NOTE: This function probably shouldn't call error(). */ 261 262 static ptid_t 263 thread_to_lwp (ptid_t thread_id, int default_lwp) 264 { 265 td_thrinfo_t ti; 266 td_thrhandle_t th; 267 td_err_e val; 268 269 if (ptid_lwp_p (thread_id)) 270 return thread_id; /* It's already an LWP ID. */ 271 272 /* It's a thread. Convert to LWP. */ 273 274 val = p_td_ta_map_id2thr (main_ta, ptid_get_tid (thread_id), &th); 275 if (val == TD_NOTHR) 276 return pid_to_ptid (-1); /* Thread must have terminated. */ 277 else if (val != TD_OK) 278 error (_("thread_to_lwp: td_ta_map_id2thr %s"), td_err_string (val)); 279 280 val = p_td_thr_get_info (&th, &ti); 281 if (val == TD_NOTHR) 282 return pid_to_ptid (-1); /* Thread must have terminated. */ 283 else if (val != TD_OK) 284 error (_("thread_to_lwp: td_thr_get_info: %s"), td_err_string (val)); 285 286 if (ti.ti_state != TD_THR_ACTIVE) 287 { 288 if (default_lwp != -1) 289 return pid_to_ptid (default_lwp); 290 error (_("thread_to_lwp: thread state not active: %s"), 291 td_state_string (ti.ti_state)); 292 } 293 294 return ptid_build (ptid_get_pid (thread_id), ti.ti_lid, 0); 295 } 296 297 /* Convert an LWP ID into a POSIX or Solaris thread ID. If LWP_ID 298 doesn't exists, that's an error. 299 300 NOTE: This function probably shouldn't call error(). */ 301 302 static ptid_t 303 lwp_to_thread (ptid_t lwp) 304 { 305 td_thrinfo_t ti; 306 td_thrhandle_t th; 307 td_err_e val; 308 309 if (ptid_tid_p (lwp)) 310 return lwp; /* It's already a thread ID. */ 311 312 /* It's an LWP. Convert it to a thread ID. */ 313 314 if (!target_thread_alive (lwp)) 315 return pid_to_ptid (-1); /* Must be a defunct LPW. */ 316 317 val = p_td_ta_map_lwp2thr (main_ta, ptid_get_lwp (lwp), &th); 318 if (val == TD_NOTHR) 319 return pid_to_ptid (-1); /* Thread must have terminated. */ 320 else if (val != TD_OK) 321 error (_("lwp_to_thread: td_ta_map_lwp2thr: %s."), td_err_string (val)); 322 323 val = p_td_thr_validate (&th); 324 if (val == TD_NOTHR) 325 return lwp; /* Unknown to libthread; just return LPW, */ 326 else if (val != TD_OK) 327 error (_("lwp_to_thread: td_thr_validate: %s."), td_err_string (val)); 328 329 val = p_td_thr_get_info (&th, &ti); 330 if (val == TD_NOTHR) 331 return pid_to_ptid (-1); /* Thread must have terminated. */ 332 else if (val != TD_OK) 333 error (_("lwp_to_thread: td_thr_get_info: %s."), td_err_string (val)); 334 335 return ptid_build (ptid_get_pid (lwp), 0 , ti.ti_tid); 336 } 337 338 339 /* Most target vector functions from here on actually just pass 340 through to the layer beneath, as they don't need to do anything 341 specific for threads. */ 342 343 /* Take a program previously attached to and detaches it. The program 344 resumes execution and will no longer stop on signals, etc. We'd 345 better not have left any breakpoints in the program or it'll die 346 when it hits one. For this to work, it may be necessary for the 347 process to have been previously attached. It *might* work if the 348 program was started via the normal ptrace (PTRACE_TRACEME). */ 349 350 static void 351 sol_thread_detach (struct target_ops *ops, const char *args, int from_tty) 352 { 353 struct target_ops *beneath = find_target_beneath (ops); 354 355 sol_thread_active = 0; 356 inferior_ptid = pid_to_ptid (ptid_get_pid (main_ph.ptid)); 357 unpush_target (ops); 358 beneath->to_detach (beneath, args, from_tty); 359 } 360 361 /* Resume execution of process PTID. If STEP is nozero, then just 362 single step it. If SIGNAL is nonzero, restart it with that signal 363 activated. We may have to convert PTID from a thread ID to an LWP 364 ID for procfs. */ 365 366 static void 367 sol_thread_resume (struct target_ops *ops, 368 ptid_t ptid, int step, enum gdb_signal signo) 369 { 370 struct cleanup *old_chain; 371 struct target_ops *beneath = find_target_beneath (ops); 372 373 old_chain = save_inferior_ptid (); 374 375 inferior_ptid = thread_to_lwp (inferior_ptid, ptid_get_pid (main_ph.ptid)); 376 if (ptid_get_pid (inferior_ptid) == -1) 377 inferior_ptid = procfs_first_available (); 378 379 if (ptid_get_pid (ptid) != -1) 380 { 381 ptid_t save_ptid = ptid; 382 383 ptid = thread_to_lwp (ptid, -2); 384 if (ptid_get_pid (ptid) == -2) /* Inactive thread. */ 385 error (_("This version of Solaris can't start inactive threads.")); 386 if (info_verbose && ptid_get_pid (ptid) == -1) 387 warning (_("Specified thread %ld seems to have terminated"), 388 ptid_get_tid (save_ptid)); 389 } 390 391 beneath->to_resume (beneath, ptid, step, signo); 392 393 do_cleanups (old_chain); 394 } 395 396 /* Wait for any threads to stop. We may have to convert PTID from a 397 thread ID to an LWP ID, and vice versa on the way out. */ 398 399 static ptid_t 400 sol_thread_wait (struct target_ops *ops, 401 ptid_t ptid, struct target_waitstatus *ourstatus, int options) 402 { 403 ptid_t rtnval; 404 ptid_t save_ptid; 405 struct target_ops *beneath = find_target_beneath (ops); 406 struct cleanup *old_chain; 407 408 save_ptid = inferior_ptid; 409 old_chain = save_inferior_ptid (); 410 411 inferior_ptid = thread_to_lwp (inferior_ptid, ptid_get_pid (main_ph.ptid)); 412 if (ptid_get_pid (inferior_ptid) == -1) 413 inferior_ptid = procfs_first_available (); 414 415 if (ptid_get_pid (ptid) != -1) 416 { 417 ptid_t save_ptid = ptid; 418 419 ptid = thread_to_lwp (ptid, -2); 420 if (ptid_get_pid (ptid) == -2) /* Inactive thread. */ 421 error (_("This version of Solaris can't start inactive threads.")); 422 if (info_verbose && ptid_get_pid (ptid) == -1) 423 warning (_("Specified thread %ld seems to have terminated"), 424 ptid_get_tid (save_ptid)); 425 } 426 427 rtnval = beneath->to_wait (beneath, ptid, ourstatus, options); 428 429 if (ourstatus->kind != TARGET_WAITKIND_EXITED) 430 { 431 /* Map the LWP of interest back to the appropriate thread ID. */ 432 rtnval = lwp_to_thread (rtnval); 433 if (ptid_get_pid (rtnval) == -1) 434 rtnval = save_ptid; 435 436 /* See if we have a new thread. */ 437 if (ptid_tid_p (rtnval) 438 && !ptid_equal (rtnval, save_ptid) 439 && (!in_thread_list (rtnval) 440 || is_exited (rtnval))) 441 add_thread (rtnval); 442 } 443 444 /* During process initialization, we may get here without the thread 445 package being initialized, since that can only happen after we've 446 found the shared libs. */ 447 448 do_cleanups (old_chain); 449 450 return rtnval; 451 } 452 453 static void 454 sol_thread_fetch_registers (struct target_ops *ops, 455 struct regcache *regcache, int regnum) 456 { 457 thread_t thread; 458 td_thrhandle_t thandle; 459 td_err_e val; 460 prgregset_t gregset; 461 prfpregset_t fpregset; 462 gdb_gregset_t *gregset_p = &gregset; 463 gdb_fpregset_t *fpregset_p = &fpregset; 464 struct target_ops *beneath = find_target_beneath (ops); 465 ptid_t ptid = regcache_get_ptid (regcache); 466 467 if (!ptid_tid_p (ptid)) 468 { 469 /* It's an LWP; pass the request on to the layer beneath. */ 470 beneath->to_fetch_registers (beneath, regcache, regnum); 471 return; 472 } 473 474 /* Solaris thread: convert PTID into a td_thrhandle_t. */ 475 thread = ptid_get_tid (ptid); 476 if (thread == 0) 477 error (_("sol_thread_fetch_registers: thread == 0")); 478 479 val = p_td_ta_map_id2thr (main_ta, thread, &thandle); 480 if (val != TD_OK) 481 error (_("sol_thread_fetch_registers: td_ta_map_id2thr: %s"), 482 td_err_string (val)); 483 484 /* Get the general-purpose registers. */ 485 486 val = p_td_thr_getgregs (&thandle, gregset); 487 if (val != TD_OK && val != TD_PARTIALREG) 488 error (_("sol_thread_fetch_registers: td_thr_getgregs %s"), 489 td_err_string (val)); 490 491 /* For SPARC, TD_PARTIALREG means that only %i0...%i7, %l0..%l7, %pc 492 and %sp are saved (by a thread context switch). */ 493 494 /* And, now the floating-point registers. */ 495 496 val = p_td_thr_getfpregs (&thandle, &fpregset); 497 if (val != TD_OK && val != TD_NOFPREGS) 498 error (_("sol_thread_fetch_registers: td_thr_getfpregs %s"), 499 td_err_string (val)); 500 501 /* Note that we must call supply_gregset and supply_fpregset *after* 502 calling the td routines because the td routines call ps_lget* 503 which affect the values stored in the registers array. */ 504 505 supply_gregset (regcache, (const gdb_gregset_t *) gregset_p); 506 supply_fpregset (regcache, (const gdb_fpregset_t *) fpregset_p); 507 } 508 509 static void 510 sol_thread_store_registers (struct target_ops *ops, 511 struct regcache *regcache, int regnum) 512 { 513 thread_t thread; 514 td_thrhandle_t thandle; 515 td_err_e val; 516 prgregset_t gregset; 517 prfpregset_t fpregset; 518 ptid_t ptid = regcache_get_ptid (regcache); 519 520 if (!ptid_tid_p (ptid)) 521 { 522 struct target_ops *beneath = find_target_beneath (ops); 523 524 /* It's an LWP; pass the request on to the layer beneath. */ 525 beneath->to_store_registers (beneath, regcache, regnum); 526 return; 527 } 528 529 /* Solaris thread: convert PTID into a td_thrhandle_t. */ 530 thread = ptid_get_tid (ptid); 531 532 val = p_td_ta_map_id2thr (main_ta, thread, &thandle); 533 if (val != TD_OK) 534 error (_("sol_thread_store_registers: td_ta_map_id2thr %s"), 535 td_err_string (val)); 536 537 if (regnum != -1) 538 { 539 val = p_td_thr_getgregs (&thandle, gregset); 540 if (val != TD_OK) 541 error (_("sol_thread_store_registers: td_thr_getgregs %s"), 542 td_err_string (val)); 543 val = p_td_thr_getfpregs (&thandle, &fpregset); 544 if (val != TD_OK) 545 error (_("sol_thread_store_registers: td_thr_getfpregs %s"), 546 td_err_string (val)); 547 } 548 549 fill_gregset (regcache, (gdb_gregset_t *) &gregset, regnum); 550 fill_fpregset (regcache, (gdb_fpregset_t *) &fpregset, regnum); 551 552 val = p_td_thr_setgregs (&thandle, gregset); 553 if (val != TD_OK) 554 error (_("sol_thread_store_registers: td_thr_setgregs %s"), 555 td_err_string (val)); 556 val = p_td_thr_setfpregs (&thandle, &fpregset); 557 if (val != TD_OK) 558 error (_("sol_thread_store_registers: td_thr_setfpregs %s"), 559 td_err_string (val)); 560 } 561 562 /* Perform partial transfers on OBJECT. See target_read_partial and 563 target_write_partial for details of each variant. One, and only 564 one, of readbuf or writebuf must be non-NULL. */ 565 566 static enum target_xfer_status 567 sol_thread_xfer_partial (struct target_ops *ops, enum target_object object, 568 const char *annex, gdb_byte *readbuf, 569 const gdb_byte *writebuf, 570 ULONGEST offset, ULONGEST len, ULONGEST *xfered_len) 571 { 572 enum target_xfer_status retval; 573 struct cleanup *old_chain; 574 struct target_ops *beneath = find_target_beneath (ops); 575 576 old_chain = save_inferior_ptid (); 577 578 if (ptid_tid_p (inferior_ptid) || !target_thread_alive (inferior_ptid)) 579 { 580 /* It's either a thread or an LWP that isn't alive. Any live 581 LWP will do so use the first available. 582 583 NOTE: We don't need to call switch_to_thread; we're just 584 reading memory. */ 585 inferior_ptid = procfs_first_available (); 586 } 587 588 retval = beneath->to_xfer_partial (beneath, object, annex, readbuf, 589 writebuf, offset, len, xfered_len); 590 591 do_cleanups (old_chain); 592 593 return retval; 594 } 595 596 static void 597 check_for_thread_db (void) 598 { 599 td_err_e err; 600 ptid_t ptid; 601 602 /* Don't attempt to use thread_db for remote targets. */ 603 if (!(target_can_run (¤t_target) || core_bfd)) 604 return; 605 606 /* Do nothing if we couldn't load libthread_db.so.1. */ 607 if (p_td_ta_new == NULL) 608 return; 609 610 if (sol_thread_active) 611 /* Nothing to do. The thread library was already detected and the 612 target vector was already activated. */ 613 return; 614 615 /* Now, initialize libthread_db. This needs to be done after the 616 shared libraries are located because it needs information from 617 the user's thread library. */ 618 619 err = p_td_init (); 620 if (err != TD_OK) 621 { 622 warning (_("sol_thread_new_objfile: td_init: %s"), td_err_string (err)); 623 return; 624 } 625 626 /* Now attempt to open a connection to the thread library. */ 627 err = p_td_ta_new (&main_ph, &main_ta); 628 switch (err) 629 { 630 case TD_NOLIBTHREAD: 631 /* No thread library was detected. */ 632 break; 633 634 case TD_OK: 635 printf_unfiltered (_("[Thread debugging using libthread_db enabled]\n")); 636 637 /* The thread library was detected. Activate the sol_thread target. */ 638 push_target (&sol_thread_ops); 639 sol_thread_active = 1; 640 641 main_ph.ptid = inferior_ptid; /* Save for xfer_memory. */ 642 ptid = lwp_to_thread (inferior_ptid); 643 if (ptid_get_pid (ptid) != -1) 644 inferior_ptid = ptid; 645 646 target_update_thread_list (); 647 break; 648 649 default: 650 warning (_("Cannot initialize thread debugging library: %s"), 651 td_err_string (err)); 652 break; 653 } 654 } 655 656 /* This routine is called whenever a new symbol table is read in, or 657 when all symbol tables are removed. libthread_db can only be 658 initialized when it finds the right variables in libthread.so. 659 Since it's a shared library, those variables don't show up until 660 the library gets mapped and the symbol table is read in. */ 661 662 static void 663 sol_thread_new_objfile (struct objfile *objfile) 664 { 665 if (objfile != NULL) 666 check_for_thread_db (); 667 } 668 669 /* Clean up after the inferior dies. */ 670 671 static void 672 sol_thread_mourn_inferior (struct target_ops *ops) 673 { 674 struct target_ops *beneath = find_target_beneath (ops); 675 676 sol_thread_active = 0; 677 678 unpush_target (ops); 679 680 beneath->to_mourn_inferior (beneath); 681 } 682 683 /* Return true if PTID is still active in the inferior. */ 684 685 static int 686 sol_thread_alive (struct target_ops *ops, ptid_t ptid) 687 { 688 if (ptid_tid_p (ptid)) 689 { 690 /* It's a (user-level) thread. */ 691 td_err_e val; 692 td_thrhandle_t th; 693 int pid; 694 695 pid = ptid_get_tid (ptid); 696 if ((val = p_td_ta_map_id2thr (main_ta, pid, &th)) != TD_OK) 697 return 0; /* Thread not found. */ 698 if ((val = p_td_thr_validate (&th)) != TD_OK) 699 return 0; /* Thread not valid. */ 700 return 1; /* Known thread. */ 701 } 702 else 703 { 704 struct target_ops *beneath = find_target_beneath (ops); 705 706 /* It's an LPW; pass the request on to the layer below. */ 707 return beneath->to_thread_alive (beneath, ptid); 708 } 709 } 710 711 712 /* These routines implement the lower half of the thread_db interface, 713 i.e. the ps_* routines. */ 714 715 /* Various versions of <proc_service.h> have slightly different 716 function prototypes. In particular, we have 717 718 NEWER OLDER 719 struct ps_prochandle * const struct ps_prochandle * 720 void* char* 721 const void* char* 722 int size_t 723 724 Which one you have depends on the Solaris version and what patches 725 you've applied. On the theory that there are only two major 726 variants, we have configure check the prototype of ps_pdwrite (), 727 and use that info to make appropriate typedefs here. */ 728 729 #ifdef PROC_SERVICE_IS_OLD 730 typedef const struct ps_prochandle *gdb_ps_prochandle_t; 731 typedef char *gdb_ps_read_buf_t; 732 typedef char *gdb_ps_write_buf_t; 733 typedef int gdb_ps_size_t; 734 typedef psaddr_t gdb_ps_addr_t; 735 #else 736 typedef struct ps_prochandle *gdb_ps_prochandle_t; 737 typedef void *gdb_ps_read_buf_t; 738 typedef const void *gdb_ps_write_buf_t; 739 typedef size_t gdb_ps_size_t; 740 typedef psaddr_t gdb_ps_addr_t; 741 #endif 742 743 /* The next four routines are called by libthread_db to tell us to 744 stop and stop a particular process or lwp. Since GDB ensures that 745 these are all stopped by the time we call anything in thread_db, 746 these routines need to do nothing. */ 747 748 /* Process stop. */ 749 750 ps_err_e 751 ps_pstop (gdb_ps_prochandle_t ph) 752 { 753 return PS_OK; 754 } 755 756 /* Process continue. */ 757 758 ps_err_e 759 ps_pcontinue (gdb_ps_prochandle_t ph) 760 { 761 return PS_OK; 762 } 763 764 /* LWP stop. */ 765 766 ps_err_e 767 ps_lstop (gdb_ps_prochandle_t ph, lwpid_t lwpid) 768 { 769 return PS_OK; 770 } 771 772 /* LWP continue. */ 773 774 ps_err_e 775 ps_lcontinue (gdb_ps_prochandle_t ph, lwpid_t lwpid) 776 { 777 return PS_OK; 778 } 779 780 /* Looks up the symbol LD_SYMBOL_NAME in the debugger's symbol table. */ 781 782 ps_err_e 783 ps_pglobal_lookup (gdb_ps_prochandle_t ph, const char *ld_object_name, 784 const char *ld_symbol_name, gdb_ps_addr_t *ld_symbol_addr) 785 { 786 struct bound_minimal_symbol ms; 787 788 ms = lookup_minimal_symbol (ld_symbol_name, NULL, NULL); 789 if (!ms.minsym) 790 return PS_NOSYM; 791 792 *ld_symbol_addr = BMSYMBOL_VALUE_ADDRESS (ms); 793 return PS_OK; 794 } 795 796 /* Common routine for reading and writing memory. */ 797 798 static ps_err_e 799 rw_common (int dowrite, const struct ps_prochandle *ph, gdb_ps_addr_t addr, 800 gdb_byte *buf, int size) 801 { 802 int ret; 803 struct cleanup *old_chain; 804 805 old_chain = save_inferior_ptid (); 806 807 if (ptid_tid_p (inferior_ptid) || !target_thread_alive (inferior_ptid)) 808 { 809 /* It's either a thread or an LWP that isn't alive. Any live 810 LWP will do so use the first available. 811 812 NOTE: We don't need to call switch_to_thread; we're just 813 reading memory. */ 814 inferior_ptid = procfs_first_available (); 815 } 816 817 #if defined (__sparcv9) 818 /* For Sparc64 cross Sparc32, make sure the address has not been 819 accidentally sign-extended (or whatever) to beyond 32 bits. */ 820 if (bfd_get_arch_size (exec_bfd) == 32) 821 addr &= 0xffffffff; 822 #endif 823 824 if (dowrite) 825 ret = target_write_memory (addr, (gdb_byte *) buf, size); 826 else 827 ret = target_read_memory (addr, (gdb_byte *) buf, size); 828 829 do_cleanups (old_chain); 830 831 return (ret == 0 ? PS_OK : PS_ERR); 832 } 833 834 /* Copies SIZE bytes from target process .data segment to debugger memory. */ 835 836 ps_err_e 837 ps_pdread (gdb_ps_prochandle_t ph, gdb_ps_addr_t addr, 838 gdb_ps_read_buf_t buf, gdb_ps_size_t size) 839 { 840 return rw_common (0, ph, addr, (gdb_byte *) buf, size); 841 } 842 843 /* Copies SIZE bytes from debugger memory .data segment to target process. */ 844 845 ps_err_e 846 ps_pdwrite (gdb_ps_prochandle_t ph, gdb_ps_addr_t addr, 847 gdb_ps_write_buf_t buf, gdb_ps_size_t size) 848 { 849 return rw_common (1, ph, addr, (gdb_byte *) buf, size); 850 } 851 852 /* Copies SIZE bytes from target process .text segment to debugger memory. */ 853 854 ps_err_e 855 ps_ptread (gdb_ps_prochandle_t ph, gdb_ps_addr_t addr, 856 gdb_ps_read_buf_t buf, gdb_ps_size_t size) 857 { 858 return rw_common (0, ph, addr, (gdb_byte *) buf, size); 859 } 860 861 /* Copies SIZE bytes from debugger memory .text segment to target process. */ 862 863 ps_err_e 864 ps_ptwrite (gdb_ps_prochandle_t ph, gdb_ps_addr_t addr, 865 gdb_ps_write_buf_t buf, gdb_ps_size_t size) 866 { 867 return rw_common (1, ph, addr, (gdb_byte *) buf, size); 868 } 869 870 /* Get general-purpose registers for LWP. */ 871 872 ps_err_e 873 ps_lgetregs (gdb_ps_prochandle_t ph, lwpid_t lwpid, prgregset_t gregset) 874 { 875 ptid_t ptid = ptid_build (ptid_get_pid (inferior_ptid), lwpid, 0); 876 struct regcache *regcache 877 = get_thread_arch_regcache (ptid, target_gdbarch ()); 878 879 target_fetch_registers (regcache, -1); 880 fill_gregset (regcache, (gdb_gregset_t *) gregset, -1); 881 882 return PS_OK; 883 } 884 885 /* Set general-purpose registers for LWP. */ 886 887 ps_err_e 888 ps_lsetregs (gdb_ps_prochandle_t ph, lwpid_t lwpid, 889 const prgregset_t gregset) 890 { 891 ptid_t ptid = ptid_build (ptid_get_pid (inferior_ptid), lwpid, 0); 892 struct regcache *regcache 893 = get_thread_arch_regcache (ptid, target_gdbarch ()); 894 895 supply_gregset (regcache, (const gdb_gregset_t *) gregset); 896 target_store_registers (regcache, -1); 897 898 return PS_OK; 899 } 900 901 /* Log a message (sends to gdb_stderr). */ 902 903 void 904 ps_plog (const char *fmt, ...) 905 { 906 va_list args; 907 908 va_start (args, fmt); 909 910 vfprintf_filtered (gdb_stderr, fmt, args); 911 } 912 913 /* Get size of extra register set. Currently a noop. */ 914 915 ps_err_e 916 ps_lgetxregsize (gdb_ps_prochandle_t ph, lwpid_t lwpid, int *xregsize) 917 { 918 return PS_OK; 919 } 920 921 /* Get extra register set. Currently a noop. */ 922 923 ps_err_e 924 ps_lgetxregs (gdb_ps_prochandle_t ph, lwpid_t lwpid, caddr_t xregset) 925 { 926 return PS_OK; 927 } 928 929 /* Set extra register set. Currently a noop. */ 930 931 ps_err_e 932 ps_lsetxregs (gdb_ps_prochandle_t ph, lwpid_t lwpid, caddr_t xregset) 933 { 934 return PS_OK; 935 } 936 937 /* Get floating-point registers for LWP. */ 938 939 ps_err_e 940 ps_lgetfpregs (gdb_ps_prochandle_t ph, lwpid_t lwpid, 941 prfpregset_t *fpregset) 942 { 943 ptid_t ptid = ptid_build (ptid_get_pid (inferior_ptid), lwpid, 0); 944 struct regcache *regcache 945 = get_thread_arch_regcache (ptid, target_gdbarch ()); 946 947 target_fetch_registers (regcache, -1); 948 fill_fpregset (regcache, (gdb_fpregset_t *) fpregset, -1); 949 950 return PS_OK; 951 } 952 953 /* Set floating-point regs for LWP. */ 954 955 ps_err_e 956 ps_lsetfpregs (gdb_ps_prochandle_t ph, lwpid_t lwpid, 957 const prfpregset_t * fpregset) 958 { 959 ptid_t ptid = ptid_build (ptid_get_pid (inferior_ptid), lwpid, 0); 960 struct regcache *regcache 961 = get_thread_arch_regcache (ptid, target_gdbarch ()); 962 963 supply_fpregset (regcache, (const gdb_fpregset_t *) fpregset); 964 target_store_registers (regcache, -1); 965 966 return PS_OK; 967 } 968 969 #ifdef PR_MODEL_LP64 970 /* Identify process as 32-bit or 64-bit. At the moment we're using 971 BFD to do this. There might be a more Solaris-specific 972 (e.g. procfs) method, but this ought to work. */ 973 974 ps_err_e 975 ps_pdmodel (gdb_ps_prochandle_t ph, int *data_model) 976 { 977 if (exec_bfd == 0) 978 *data_model = PR_MODEL_UNKNOWN; 979 else if (bfd_get_arch_size (exec_bfd) == 32) 980 *data_model = PR_MODEL_ILP32; 981 else 982 *data_model = PR_MODEL_LP64; 983 984 return PS_OK; 985 } 986 #endif /* PR_MODEL_LP64 */ 987 988 #if (defined(__i386__) || defined(__x86_64__)) && defined (sun) 989 990 /* Reads the local descriptor table of a LWP. 991 992 This function is necessary on x86-solaris only. Without it, the loading 993 of libthread_db would fail because of ps_lgetLDT being undefined. */ 994 995 ps_err_e 996 ps_lgetLDT (gdb_ps_prochandle_t ph, lwpid_t lwpid, 997 struct ssd *pldt) 998 { 999 /* NOTE: only used on Solaris, therefore OK to refer to procfs.c. */ 1000 struct ssd *ret; 1001 1002 /* FIXME: can't I get the process ID from the prochandle or 1003 something? */ 1004 1005 if (ptid_get_pid (inferior_ptid) <= 0 || lwpid <= 0) 1006 return PS_BADLID; 1007 1008 ret = procfs_find_LDT_entry (ptid_build (ptid_get_pid (inferior_ptid), 1009 lwpid, 0)); 1010 if (ret) 1011 { 1012 memcpy (pldt, ret, sizeof (struct ssd)); 1013 return PS_OK; 1014 } 1015 else 1016 /* LDT not found. */ 1017 return PS_ERR; 1018 } 1019 #endif 1020 1021 1022 /* Convert PTID to printable form. */ 1023 1024 static const char * 1025 solaris_pid_to_str (struct target_ops *ops, ptid_t ptid) 1026 { 1027 static char buf[100]; 1028 1029 if (ptid_tid_p (ptid)) 1030 { 1031 ptid_t lwp; 1032 1033 lwp = thread_to_lwp (ptid, -2); 1034 1035 if (ptid_get_pid (lwp) == -1) 1036 xsnprintf (buf, sizeof (buf), "Thread %ld (defunct)", 1037 ptid_get_tid (ptid)); 1038 else if (ptid_get_pid (lwp) != -2) 1039 xsnprintf (buf, sizeof (buf), "Thread %ld (LWP %ld)", 1040 ptid_get_tid (ptid), ptid_get_lwp (lwp)); 1041 else 1042 xsnprintf (buf, sizeof (buf), "Thread %ld ", 1043 ptid_get_tid (ptid)); 1044 } 1045 else if (ptid_get_lwp (ptid) != 0) 1046 xsnprintf (buf, sizeof (buf), "LWP %ld ", ptid_get_lwp (ptid)); 1047 else 1048 xsnprintf (buf, sizeof (buf), "process %d ", ptid_get_pid (ptid)); 1049 1050 return buf; 1051 } 1052 1053 1054 /* Worker bee for update_thread_list. Callback function that gets 1055 called once per user-level thread (i.e. not for LWP's). */ 1056 1057 static int 1058 sol_update_thread_list_callback (const td_thrhandle_t *th, void *ignored) 1059 { 1060 td_err_e retval; 1061 td_thrinfo_t ti; 1062 ptid_t ptid; 1063 1064 retval = p_td_thr_get_info (th, &ti); 1065 if (retval != TD_OK) 1066 return -1; 1067 1068 ptid = ptid_build (ptid_get_pid (inferior_ptid), 0, ti.ti_tid); 1069 if (!in_thread_list (ptid) || is_exited (ptid)) 1070 add_thread (ptid); 1071 1072 return 0; 1073 } 1074 1075 static void 1076 sol_update_thread_list (struct target_ops *ops) 1077 { 1078 struct target_ops *beneath = find_target_beneath (ops); 1079 1080 /* Delete dead threads. */ 1081 prune_threads (); 1082 1083 /* Find any new LWP's. */ 1084 beneath->to_update_thread_list (beneath); 1085 1086 /* Then find any new user-level threads. */ 1087 p_td_ta_thr_iter (main_ta, sol_update_thread_list_callback, (void *) 0, 1088 TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY, 1089 TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS); 1090 } 1091 1092 /* Worker bee for the "info sol-thread" command. This is a callback 1093 function that gets called once for each Solaris user-level thread 1094 (i.e. not for LWPs) in the inferior. Print anything interesting 1095 that we can think of. */ 1096 1097 static int 1098 info_cb (const td_thrhandle_t *th, void *s) 1099 { 1100 td_err_e ret; 1101 td_thrinfo_t ti; 1102 1103 ret = p_td_thr_get_info (th, &ti); 1104 if (ret == TD_OK) 1105 { 1106 printf_filtered ("%s thread #%d, lwp %d, ", 1107 ti.ti_type == TD_THR_SYSTEM ? "system" : "user ", 1108 ti.ti_tid, ti.ti_lid); 1109 switch (ti.ti_state) 1110 { 1111 default: 1112 case TD_THR_UNKNOWN: 1113 printf_filtered ("<unknown state>"); 1114 break; 1115 case TD_THR_STOPPED: 1116 printf_filtered ("(stopped)"); 1117 break; 1118 case TD_THR_RUN: 1119 printf_filtered ("(run) "); 1120 break; 1121 case TD_THR_ACTIVE: 1122 printf_filtered ("(active) "); 1123 break; 1124 case TD_THR_ZOMBIE: 1125 printf_filtered ("(zombie) "); 1126 break; 1127 case TD_THR_SLEEP: 1128 printf_filtered ("(asleep) "); 1129 break; 1130 case TD_THR_STOPPED_ASLEEP: 1131 printf_filtered ("(stopped asleep)"); 1132 break; 1133 } 1134 /* Print thr_create start function. */ 1135 if (ti.ti_startfunc != 0) 1136 { 1137 const struct bound_minimal_symbol msym 1138 = lookup_minimal_symbol_by_pc (ti.ti_startfunc); 1139 1140 printf_filtered (" startfunc=%s", 1141 msym.minsym 1142 ? MSYMBOL_PRINT_NAME (msym.minsym) 1143 : paddress (target_gdbarch (), ti.ti_startfunc)); 1144 } 1145 1146 /* If thread is asleep, print function that went to sleep. */ 1147 if (ti.ti_state == TD_THR_SLEEP) 1148 { 1149 const struct bound_minimal_symbol msym 1150 = lookup_minimal_symbol_by_pc (ti.ti_pc); 1151 1152 printf_filtered (" sleepfunc=%s", 1153 msym.minsym 1154 ? MSYMBOL_PRINT_NAME (msym.minsym) 1155 : paddress (target_gdbarch (), ti.ti_pc)); 1156 } 1157 1158 printf_filtered ("\n"); 1159 } 1160 else 1161 warning (_("info sol-thread: failed to get info for thread.")); 1162 1163 return 0; 1164 } 1165 1166 /* List some state about each Solaris user-level thread in the 1167 inferior. */ 1168 1169 static void 1170 info_solthreads (char *args, int from_tty) 1171 { 1172 p_td_ta_thr_iter (main_ta, info_cb, args, 1173 TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY, 1174 TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS); 1175 } 1176 1177 /* Callback routine used to find a thread based on the TID part of 1178 its PTID. */ 1179 1180 static int 1181 thread_db_find_thread_from_tid (struct thread_info *thread, void *data) 1182 { 1183 long *tid = (long *) data; 1184 1185 if (ptid_get_tid (thread->ptid) == *tid) 1186 return 1; 1187 1188 return 0; 1189 } 1190 1191 static ptid_t 1192 sol_get_ada_task_ptid (struct target_ops *self, long lwp, long thread) 1193 { 1194 struct thread_info *thread_info = 1195 iterate_over_threads (thread_db_find_thread_from_tid, &thread); 1196 1197 if (thread_info == NULL) 1198 { 1199 /* The list of threads is probably not up to date. Find any 1200 thread that is missing from the list, and try again. */ 1201 sol_update_thread_list (¤t_target); 1202 thread_info = iterate_over_threads (thread_db_find_thread_from_tid, 1203 &thread); 1204 } 1205 1206 gdb_assert (thread_info != NULL); 1207 1208 return (thread_info->ptid); 1209 } 1210 1211 static void 1212 init_sol_thread_ops (void) 1213 { 1214 sol_thread_ops.to_shortname = "solaris-threads"; 1215 sol_thread_ops.to_longname = "Solaris threads and pthread."; 1216 sol_thread_ops.to_doc = "Solaris threads and pthread support."; 1217 sol_thread_ops.to_detach = sol_thread_detach; 1218 sol_thread_ops.to_resume = sol_thread_resume; 1219 sol_thread_ops.to_wait = sol_thread_wait; 1220 sol_thread_ops.to_fetch_registers = sol_thread_fetch_registers; 1221 sol_thread_ops.to_store_registers = sol_thread_store_registers; 1222 sol_thread_ops.to_xfer_partial = sol_thread_xfer_partial; 1223 sol_thread_ops.to_mourn_inferior = sol_thread_mourn_inferior; 1224 sol_thread_ops.to_thread_alive = sol_thread_alive; 1225 sol_thread_ops.to_pid_to_str = solaris_pid_to_str; 1226 sol_thread_ops.to_update_thread_list = sol_update_thread_list; 1227 sol_thread_ops.to_stratum = thread_stratum; 1228 sol_thread_ops.to_get_ada_task_ptid = sol_get_ada_task_ptid; 1229 sol_thread_ops.to_magic = OPS_MAGIC; 1230 } 1231 1232 /* Silence -Wmissing-prototypes. */ 1233 extern void _initialize_sol_thread (void); 1234 1235 void 1236 _initialize_sol_thread (void) 1237 { 1238 void *dlhandle; 1239 1240 init_sol_thread_ops (); 1241 1242 dlhandle = dlopen ("libthread_db.so.1", RTLD_NOW); 1243 if (!dlhandle) 1244 goto die; 1245 1246 #define resolve(X) \ 1247 if (!(p_##X = (X ## _ftype *) dlsym (dlhandle, #X))) \ 1248 goto die; 1249 1250 resolve (td_log); 1251 resolve (td_ta_new); 1252 resolve (td_ta_delete); 1253 resolve (td_init); 1254 resolve (td_ta_get_ph); 1255 resolve (td_ta_get_nthreads); 1256 resolve (td_ta_tsd_iter); 1257 resolve (td_ta_thr_iter); 1258 resolve (td_thr_validate); 1259 resolve (td_thr_tsd); 1260 resolve (td_thr_get_info); 1261 resolve (td_thr_getfpregs); 1262 resolve (td_thr_getxregsize); 1263 resolve (td_thr_getxregs); 1264 resolve (td_thr_sigsetmask); 1265 resolve (td_thr_setprio); 1266 resolve (td_thr_setsigpending); 1267 resolve (td_thr_setfpregs); 1268 resolve (td_thr_setxregs); 1269 resolve (td_ta_map_id2thr); 1270 resolve (td_ta_map_lwp2thr); 1271 resolve (td_thr_getgregs); 1272 resolve (td_thr_setgregs); 1273 1274 complete_target_initialization (&sol_thread_ops); 1275 1276 add_cmd ("sol-threads", class_maintenance, info_solthreads, 1277 _("Show info on Solaris user threads."), &maintenanceinfolist); 1278 1279 /* Hook into new_objfile notification. */ 1280 observer_attach_new_objfile (sol_thread_new_objfile); 1281 return; 1282 1283 die: 1284 fprintf_unfiltered (gdb_stderr, "\ 1285 [GDB will not be able to debug user-mode threads: %s]\n", dlerror ()); 1286 1287 if (dlhandle) 1288 dlclose (dlhandle); 1289 1290 return; 1291 } 1292