1/* QNX Neutrino specific low level interface, for the remote server 2 for GDB. 3 Copyright (C) 2009, 2010, 2011 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 21#include "server.h" 22#include "nto-low.h" 23 24#include <limits.h> 25#include <fcntl.h> 26#include <spawn.h> 27#include <sys/procfs.h> 28#include <sys/auxv.h> 29#include <stdarg.h> 30#include <sys/iomgr.h> 31#include <sys/neutrino.h> 32 33 34extern int using_threads; 35int using_threads = 1; 36 37static void 38nto_trace (const char *fmt, ...) 39{ 40 va_list arg_list; 41 42 if (debug_threads == 0) 43 return; 44 fprintf (stderr, "nto:"); 45 va_start (arg_list, fmt); 46 vfprintf (stderr, fmt, arg_list); 47 va_end (arg_list); 48} 49 50#define TRACE nto_trace 51 52/* Structure holding neutrino specific information about 53 inferior. */ 54 55struct nto_inferior 56{ 57 char nto_procfs_path[PATH_MAX]; 58 int ctl_fd; 59 pid_t pid; 60 int exit_signo; /* For tracking exit status. */ 61}; 62 63static struct nto_inferior nto_inferior; 64 65static void 66init_nto_inferior (struct nto_inferior *nto_inferior) 67{ 68 memset (nto_inferior, 0, sizeof (struct nto_inferior)); 69 nto_inferior->ctl_fd = -1; 70 nto_inferior->pid = -1; 71} 72 73static void 74do_detach (void) 75{ 76 if (nto_inferior.ctl_fd != -1) 77 { 78 nto_trace ("Closing fd\n"); 79 close (nto_inferior.ctl_fd); 80 init_nto_inferior (&nto_inferior); 81 } 82} 83 84/* Set current thread. Return 1 on success, 0 otherwise. */ 85 86static int 87nto_set_thread (ptid_t ptid) 88{ 89 int res = 0; 90 91 TRACE ("%s pid: %d tid: %ld\n", __func__, ptid_get_pid (ptid), 92 ptid_get_lwp (ptid)); 93 if (nto_inferior.ctl_fd != -1 94 && !ptid_equal (ptid, null_ptid) 95 && !ptid_equal (ptid, minus_one_ptid)) 96 { 97 pthread_t tid = ptid_get_lwp (ptid); 98 99 if (EOK == devctl (nto_inferior.ctl_fd, DCMD_PROC_CURTHREAD, &tid, 100 sizeof (tid), 0)) 101 res = 1; 102 else 103 TRACE ("%s: Error: failed to set current thread\n", __func__); 104 } 105 return res; 106} 107 108/* This function will determine all alive threads. Note that we do not list 109 dead but unjoined threads even though they are still in the process' thread 110 list. 111 112 NTO_INFERIOR must not be NULL. */ 113 114static void 115nto_find_new_threads (struct nto_inferior *nto_inferior) 116{ 117 pthread_t tid; 118 119 TRACE ("%s pid:%d\n", __func__, nto_inferior->pid); 120 121 if (nto_inferior->ctl_fd == -1) 122 return; 123 124 for (tid = 1;; ++tid) 125 { 126 procfs_status status; 127 ptid_t ptid; 128 int err; 129 130 status.tid = tid; 131 err = devctl (nto_inferior->ctl_fd, DCMD_PROC_TIDSTATUS, &status, 132 sizeof (status), 0); 133 134 if (err != EOK || status.tid == 0) 135 break; 136 137 /* All threads in between are gone. */ 138 while (tid != status.tid || status.state == STATE_DEAD) 139 { 140 struct thread_info *ti; 141 142 ptid = ptid_build (nto_inferior->pid, tid, 0); 143 ti = find_thread_ptid (ptid); 144 if (ti != NULL) 145 { 146 TRACE ("Removing thread %d\n", tid); 147 remove_thread (ti); 148 } 149 if (tid == status.tid) 150 break; 151 ++tid; 152 } 153 154 if (status.state != STATE_DEAD) 155 { 156 TRACE ("Adding thread %d\n", tid); 157 ptid = ptid_build (nto_inferior->pid, tid, 0); 158 if (!find_thread_ptid (ptid)) 159 add_thread (ptid, NULL); 160 } 161 } 162} 163 164/* Given pid, open procfs path. */ 165 166static pid_t 167do_attach (pid_t pid) 168{ 169 procfs_status status; 170 struct sigevent event; 171 172 if (nto_inferior.ctl_fd != -1) 173 { 174 close (nto_inferior.ctl_fd); 175 init_nto_inferior (&nto_inferior); 176 } 177 xsnprintf (nto_inferior.nto_procfs_path, PATH_MAX - 1, "/proc/%d/as", pid); 178 nto_inferior.ctl_fd = open (nto_inferior.nto_procfs_path, O_RDWR); 179 if (nto_inferior.ctl_fd == -1) 180 { 181 TRACE ("Failed to open %s\n", nto_inferior.nto_procfs_path); 182 init_nto_inferior (&nto_inferior); 183 return -1; 184 } 185 if (devctl (nto_inferior.ctl_fd, DCMD_PROC_STOP, &status, sizeof (status), 0) 186 != EOK) 187 { 188 do_detach (); 189 return -1; 190 } 191 nto_inferior.pid = pid; 192 /* Define a sigevent for process stopped notification. */ 193 event.sigev_notify = SIGEV_SIGNAL_THREAD; 194 event.sigev_signo = SIGUSR1; 195 event.sigev_code = 0; 196 event.sigev_value.sival_ptr = NULL; 197 event.sigev_priority = -1; 198 devctl (nto_inferior.ctl_fd, DCMD_PROC_EVENT, &event, sizeof (event), 0); 199 200 if (devctl (nto_inferior.ctl_fd, DCMD_PROC_STATUS, &status, sizeof (status), 201 0) == EOK 202 && (status.flags & _DEBUG_FLAG_STOPPED)) 203 { 204 ptid_t ptid; 205 206 kill (pid, SIGCONT); 207 ptid = ptid_build (status.pid, status.tid, 0); 208 the_low_target.arch_setup (); 209 add_process (status.pid, 1); 210 TRACE ("Adding thread: pid=%d tid=%ld\n", status.pid, 211 ptid_get_lwp (ptid)); 212 nto_find_new_threads (&nto_inferior); 213 } 214 else 215 { 216 do_detach (); 217 return -1; 218 } 219 220 return pid; 221} 222 223/* Read or write LEN bytes from/to inferior's MEMADDR memory address 224 into gdbservers's MYADDR buffer. Return number of bytes actually 225 transfered. */ 226 227static int 228nto_xfer_memory (off_t memaddr, unsigned char *myaddr, int len, 229 int dowrite) 230{ 231 int nbytes = 0; 232 233 if (lseek (nto_inferior.ctl_fd, memaddr, SEEK_SET) == memaddr) 234 { 235 if (dowrite) 236 nbytes = write (nto_inferior.ctl_fd, myaddr, len); 237 else 238 nbytes = read (nto_inferior.ctl_fd, myaddr, len); 239 if (nbytes < 0) 240 nbytes = 0; 241 } 242 if (nbytes == 0) 243 { 244 int e = errno; 245 TRACE ("Error in %s : errno=%d (%s)\n", __func__, e, strerror (e)); 246 } 247 return nbytes; 248} 249 250/* Insert or remove breakpoint or watchpoint at address ADDR. 251 TYPE can be one of Neutrino breakpoint types. SIZE must be 0 for 252 inserting the point, -1 for removing it. 253 254 Return 0 on success, 1 otherwise. */ 255 256static int 257nto_breakpoint (CORE_ADDR addr, int type, int size) 258{ 259 procfs_break brk; 260 261 brk.type = type; 262 brk.addr = addr; 263 brk.size = size; 264 if (devctl (nto_inferior.ctl_fd, DCMD_PROC_BREAK, &brk, sizeof (brk), 0) 265 != EOK) 266 return 1; 267 return 0; 268} 269 270/* Read auxiliary vector from inferior's initial stack into gdbserver's 271 MYADDR buffer, up to LEN bytes. 272 273 Return number of bytes read. */ 274 275static int 276nto_read_auxv_from_initial_stack (CORE_ADDR initial_stack, 277 unsigned char *myaddr, 278 unsigned int len) 279{ 280 int data_ofs = 0; 281 int anint; 282 unsigned int len_read = 0; 283 284 /* Skip over argc, argv and envp... Comment from ldd.c: 285 286 The startup frame is set-up so that we have: 287 auxv 288 NULL 289 ... 290 envp2 291 envp1 <----- void *frame + (argc + 2) * sizeof(char *) 292 NULL 293 ... 294 argv2 295 argv1 296 argc <------ void * frame 297 298 On entry to ldd, frame gives the address of argc on the stack. */ 299 if (nto_xfer_memory (initial_stack, (unsigned char *)&anint, 300 sizeof (anint), 0) != sizeof (anint)) 301 return 0; 302 303 /* Size of pointer is assumed to be 4 bytes (32 bit arch. ) */ 304 data_ofs += (anint + 2) * sizeof (void *); /* + 2 comes from argc itself and 305 NULL terminating pointer in 306 argv. */ 307 308 /* Now loop over env table: */ 309 while (nto_xfer_memory (initial_stack + data_ofs, 310 (unsigned char *)&anint, sizeof (anint), 0) 311 == sizeof (anint)) 312 { 313 data_ofs += sizeof (anint); 314 if (anint == 0) 315 break; 316 } 317 initial_stack += data_ofs; 318 319 memset (myaddr, 0, len); 320 while (len_read <= len - sizeof (auxv_t)) 321 { 322 auxv_t *auxv = (auxv_t *)myaddr; 323 324 /* Search backwards until we have read AT_PHDR (num. 3), 325 AT_PHENT (num 4), AT_PHNUM (num 5) */ 326 if (nto_xfer_memory (initial_stack, (unsigned char *)auxv, 327 sizeof (auxv_t), 0) == sizeof (auxv_t)) 328 { 329 if (auxv->a_type != AT_NULL) 330 { 331 auxv++; 332 len_read += sizeof (auxv_t); 333 } 334 if (auxv->a_type == AT_PHNUM) /* That's all we need. */ 335 break; 336 initial_stack += sizeof (auxv_t); 337 } 338 else 339 break; 340 } 341 TRACE ("auxv: len_read: %d\n", len_read); 342 return len_read; 343} 344 345/* Start inferior specified by PROGRAM passing arguments ALLARGS. */ 346 347static int 348nto_create_inferior (char *program, char **allargs) 349{ 350 struct inheritance inherit; 351 pid_t pid; 352 sigset_t set; 353 354 TRACE ("%s %s\n", __func__, program); 355 /* Clear any pending SIGUSR1's but keep the behavior the same. */ 356 signal (SIGUSR1, signal (SIGUSR1, SIG_IGN)); 357 358 sigemptyset (&set); 359 sigaddset (&set, SIGUSR1); 360 sigprocmask (SIG_UNBLOCK, &set, NULL); 361 362 memset (&inherit, 0, sizeof (inherit)); 363 inherit.flags |= SPAWN_SETGROUP | SPAWN_HOLD; 364 inherit.pgroup = SPAWN_NEWPGROUP; 365 pid = spawnp (program, 0, NULL, &inherit, allargs, 0); 366 sigprocmask (SIG_BLOCK, &set, NULL); 367 368 if (pid == -1) 369 return -1; 370 371 if (do_attach (pid) != pid) 372 return -1; 373 374 return pid; 375} 376 377/* Attach to process PID. */ 378 379static int 380nto_attach (unsigned long pid) 381{ 382 TRACE ("%s %ld\n", __func__, pid); 383 if (do_attach (pid) != pid) 384 error ("Unable to attach to %ld\n", pid); 385 return 0; 386} 387 388/* Send signal to process PID. */ 389 390static int 391nto_kill (int pid) 392{ 393 TRACE ("%s %d\n", __func__, pid); 394 kill (pid, SIGKILL); 395 do_detach (); 396 return 0; 397} 398 399/* Detach from process PID. */ 400 401static int 402nto_detach (int pid) 403{ 404 TRACE ("%s %d\n", __func__, pid); 405 do_detach (); 406 return 0; 407} 408 409static void 410nto_mourn (struct process_info *process) 411{ 412 remove_process (process); 413} 414 415/* Check if the given thread is alive. 416 417 Return 1 if alive, 0 otherwise. */ 418 419static int 420nto_thread_alive (ptid_t ptid) 421{ 422 int res; 423 424 TRACE ("%s pid:%d tid:%d\n", __func__, ptid_get_pid (ptid), 425 ptid_get_lwp (ptid)); 426 if (SignalKill (0, ptid_get_pid (ptid), ptid_get_lwp (ptid), 427 0, 0, 0) == -1) 428 res = 0; 429 else 430 res = 1; 431 TRACE ("%s: %s\n", __func__, res ? "yes" : "no"); 432 return res; 433} 434 435/* Resume inferior's execution. */ 436 437static void 438nto_resume (struct thread_resume *resume_info, size_t n) 439{ 440 /* We can only work in all-stop mode. */ 441 procfs_status status; 442 procfs_run run; 443 int err; 444 445 TRACE ("%s\n", __func__); 446 /* Workaround for aliasing rules violation. */ 447 sigset_t *run_fault = (sigset_t *) (void *) &run.fault; 448 449 nto_set_thread (resume_info->thread); 450 451 run.flags = _DEBUG_RUN_FAULT | _DEBUG_RUN_TRACE; 452 if (resume_info->kind == resume_step) 453 run.flags |= _DEBUG_RUN_STEP; 454 run.flags |= _DEBUG_RUN_ARM; 455 456 sigemptyset (run_fault); 457 sigaddset (run_fault, FLTBPT); 458 sigaddset (run_fault, FLTTRACE); 459 sigaddset (run_fault, FLTILL); 460 sigaddset (run_fault, FLTPRIV); 461 sigaddset (run_fault, FLTBOUNDS); 462 sigaddset (run_fault, FLTIOVF); 463 sigaddset (run_fault, FLTIZDIV); 464 sigaddset (run_fault, FLTFPE); 465 sigaddset (run_fault, FLTPAGE); 466 sigaddset (run_fault, FLTSTACK); 467 sigaddset (run_fault, FLTACCESS); 468 469 sigemptyset (&run.trace); 470 if (resume_info->sig) 471 { 472 int signal_to_pass; 473 474 devctl (nto_inferior.ctl_fd, DCMD_PROC_STATUS, &status, sizeof (status), 475 0); 476 signal_to_pass = resume_info->sig; 477 if (status.why & (_DEBUG_WHY_SIGNALLED | _DEBUG_WHY_FAULTED)) 478 { 479 if (signal_to_pass != status.info.si_signo) 480 { 481 kill (status.pid, signal_to_pass); 482 run.flags |= _DEBUG_RUN_CLRFLT | _DEBUG_RUN_CLRSIG; 483 } 484 else /* Let it kill the program without telling us. */ 485 sigdelset (&run.trace, signal_to_pass); 486 } 487 } 488 else 489 run.flags |= _DEBUG_RUN_CLRSIG | _DEBUG_RUN_CLRFLT; 490 491 sigfillset (&run.trace); 492 493 regcache_invalidate (); 494 495 err = devctl (nto_inferior.ctl_fd, DCMD_PROC_RUN, &run, sizeof (run), 0); 496 if (err != EOK) 497 TRACE ("Error: %d \"%s\"\n", err, strerror (err)); 498} 499 500/* Wait for inferior's event. 501 502 Return ptid of thread that caused the event. */ 503 504static ptid_t 505nto_wait (ptid_t ptid, 506 struct target_waitstatus *ourstatus, int target_options) 507{ 508 sigset_t set; 509 siginfo_t info; 510 procfs_status status; 511 const int trace_mask = (_DEBUG_FLAG_TRACE_EXEC | _DEBUG_FLAG_TRACE_RD 512 | _DEBUG_FLAG_TRACE_WR | _DEBUG_FLAG_TRACE_MODIFY); 513 514 TRACE ("%s\n", __func__); 515 516 ourstatus->kind = TARGET_WAITKIND_SPURIOUS; 517 518 sigemptyset (&set); 519 sigaddset (&set, SIGUSR1); 520 521 devctl (nto_inferior.ctl_fd, DCMD_PROC_STATUS, &status, sizeof (status), 0); 522 while (!(status.flags & _DEBUG_FLAG_ISTOP)) 523 { 524 sigwaitinfo (&set, &info); 525 devctl (nto_inferior.ctl_fd, DCMD_PROC_STATUS, &status, sizeof (status), 526 0); 527 } 528 nto_find_new_threads (&nto_inferior); 529 530 if (status.flags & _DEBUG_FLAG_SSTEP) 531 { 532 TRACE ("SSTEP\n"); 533 ourstatus->kind = TARGET_WAITKIND_STOPPED; 534 ourstatus->value.sig = TARGET_SIGNAL_TRAP; 535 } 536 /* Was it a breakpoint? */ 537 else if (status.flags & trace_mask) 538 { 539 TRACE ("STOPPED\n"); 540 ourstatus->kind = TARGET_WAITKIND_STOPPED; 541 ourstatus->value.sig = TARGET_SIGNAL_TRAP; 542 } 543 else if (status.flags & _DEBUG_FLAG_ISTOP) 544 { 545 TRACE ("ISTOP\n"); 546 switch (status.why) 547 { 548 case _DEBUG_WHY_SIGNALLED: 549 TRACE (" SIGNALLED\n"); 550 ourstatus->kind = TARGET_WAITKIND_STOPPED; 551 ourstatus->value.sig = 552 target_signal_from_host (status.info.si_signo); 553 nto_inferior.exit_signo = ourstatus->value.sig; 554 break; 555 case _DEBUG_WHY_FAULTED: 556 TRACE (" FAULTED\n"); 557 ourstatus->kind = TARGET_WAITKIND_STOPPED; 558 if (status.info.si_signo == SIGTRAP) 559 { 560 ourstatus->value.sig = 0; 561 nto_inferior.exit_signo = 0; 562 } 563 else 564 { 565 ourstatus->value.sig = 566 target_signal_from_host (status.info.si_signo); 567 nto_inferior.exit_signo = ourstatus->value.sig; 568 } 569 break; 570 571 case _DEBUG_WHY_TERMINATED: 572 { 573 int waitval = 0; 574 575 TRACE (" TERMINATED\n"); 576 waitpid (ptid_get_pid (ptid), &waitval, WNOHANG); 577 if (nto_inferior.exit_signo) 578 { 579 /* Abnormal death. */ 580 ourstatus->kind = TARGET_WAITKIND_SIGNALLED; 581 ourstatus->value.sig = nto_inferior.exit_signo; 582 } 583 else 584 { 585 /* Normal death. */ 586 ourstatus->kind = TARGET_WAITKIND_EXITED; 587 ourstatus->value.integer = WEXITSTATUS (waitval); 588 } 589 nto_inferior.exit_signo = 0; 590 break; 591 } 592 593 case _DEBUG_WHY_REQUESTED: 594 TRACE ("REQUESTED\n"); 595 /* We are assuming a requested stop is due to a SIGINT. */ 596 ourstatus->kind = TARGET_WAITKIND_STOPPED; 597 ourstatus->value.sig = TARGET_SIGNAL_INT; 598 nto_inferior.exit_signo = 0; 599 break; 600 } 601 } 602 603 return ptid_build (status.pid, status.tid, 0); 604} 605 606/* Fetch inferior's registers for currently selected thread (CURRENT_INFERIOR). 607 If REGNO is -1, fetch all registers, or REGNO register only otherwise. */ 608 609static void 610nto_fetch_registers (struct regcache *regcache, int regno) 611{ 612 int regsize; 613 procfs_greg greg; 614 ptid_t ptid; 615 616 TRACE ("%s (regno=%d)\n", __func__, regno); 617 if (regno >= the_low_target.num_regs) 618 return; 619 620 if (current_inferior == NULL) 621 { 622 TRACE ("current_inferior is NULL\n"); 623 return; 624 } 625 ptid = thread_to_gdb_id (current_inferior); 626 if (!nto_set_thread (ptid)) 627 return; 628 629 if (devctl (nto_inferior.ctl_fd, DCMD_PROC_GETGREG, &greg, sizeof (greg), 630 ®size) == EOK) 631 { 632 if (regno == -1) /* All registers. */ 633 { 634 for (regno = 0; regno != the_low_target.num_regs; ++regno) 635 { 636 const unsigned int registeroffset 637 = the_low_target.register_offset (regno); 638 supply_register (regcache, regno, 639 ((char *)&greg) + registeroffset); 640 } 641 } 642 else 643 { 644 const unsigned int registeroffset 645 = the_low_target.register_offset (regno); 646 if (registeroffset == -1) 647 return; 648 supply_register (regcache, regno, ((char *)&greg) + registeroffset); 649 } 650 } 651 else 652 TRACE ("ERROR reading registers from inferior.\n"); 653} 654 655/* Store registers for currently selected thread (CURRENT_INFERIOR). 656 We always store all registers, regardless of REGNO. */ 657 658static void 659nto_store_registers (struct regcache *regcache, int regno) 660{ 661 procfs_greg greg; 662 int err; 663 ptid_t ptid; 664 665 TRACE ("%s (regno:%d)\n", __func__, regno); 666 667 if (current_inferior == NULL) 668 { 669 TRACE ("current_inferior is NULL\n"); 670 return; 671 } 672 ptid = thread_to_gdb_id (current_inferior); 673 if (!nto_set_thread (ptid)) 674 return; 675 676 memset (&greg, 0, sizeof (greg)); 677 for (regno = 0; regno != the_low_target.num_regs; ++regno) 678 { 679 const unsigned int regoffset 680 = the_low_target.register_offset (regno); 681 collect_register (regcache, regno, ((char *)&greg) + regoffset); 682 } 683 err = devctl (nto_inferior.ctl_fd, DCMD_PROC_SETGREG, &greg, sizeof (greg), 684 0); 685 if (err != EOK) 686 TRACE ("Error: setting registers.\n"); 687} 688 689/* Read LEN bytes from inferior's memory address MEMADDR into 690 gdbserver's MYADDR buffer. 691 692 Return 0 on success -1 otherwise. */ 693 694static int 695nto_read_memory (CORE_ADDR memaddr, unsigned char *myaddr, int len) 696{ 697 TRACE ("%s memaddr:0x%08lx, len:%d\n", __func__, memaddr, len); 698 699 if (nto_xfer_memory (memaddr, myaddr, len, 0) != len) 700 { 701 TRACE ("Failed to read memory\n"); 702 return -1; 703 } 704 705 return 0; 706} 707 708/* Write LEN bytes from gdbserver's buffer MYADDR into inferior's 709 memory at address MEMADDR. 710 711 Return 0 on success -1 otherwise. */ 712 713static int 714nto_write_memory (CORE_ADDR memaddr, const unsigned char *myaddr, int len) 715{ 716 int len_written; 717 718 TRACE ("%s memaddr: 0x%08llx len: %d\n", __func__, memaddr, len); 719 if ((len_written = nto_xfer_memory (memaddr, (unsigned char *)myaddr, len, 720 1)) 721 != len) 722 { 723 TRACE ("Wanted to write: %d but written: %d\n", len, len_written); 724 return -1; 725 } 726 727 return 0; 728} 729 730/* Stop inferior. We always stop all threads. */ 731 732static void 733nto_request_interrupt (void) 734{ 735 TRACE ("%s\n", __func__); 736 nto_set_thread (ptid_build (nto_inferior.pid, 1, 0)); 737 if (EOK != devctl (nto_inferior.ctl_fd, DCMD_PROC_STOP, NULL, 0, 0)) 738 TRACE ("Error stopping inferior.\n"); 739} 740 741/* Read auxiliary vector from inferior's memory into gdbserver's buffer 742 MYADDR. We always read whole auxv. 743 744 Return number of bytes stored in MYADDR buffer, 0 if OFFSET > 0 745 or -1 on error. */ 746 747static int 748nto_read_auxv (CORE_ADDR offset, unsigned char *myaddr, unsigned int len) 749{ 750 int err; 751 CORE_ADDR initial_stack; 752 procfs_info procinfo; 753 754 TRACE ("%s\n", __func__); 755 if (offset > 0) 756 return 0; 757 758 err = devctl (nto_inferior.ctl_fd, DCMD_PROC_INFO, &procinfo, 759 sizeof procinfo, 0); 760 if (err != EOK) 761 return -1; 762 763 initial_stack = procinfo.initial_stack; 764 765 return nto_read_auxv_from_initial_stack (initial_stack, myaddr, len); 766} 767 768/* Insert {break/watch}point at address ADDR. 769 TYPE must be in '0'..'4' range. LEN is not used. */ 770 771static int 772nto_insert_point (char type, CORE_ADDR addr, int len) 773{ 774 int wtype = _DEBUG_BREAK_HW; /* Always request HW. */ 775 776 TRACE ("%s type:%c addr: 0x%08lx len:%d\n", __func__, (int)type, addr, len); 777 switch (type) 778 { 779 case '0': /* software-breakpoint */ 780 wtype = _DEBUG_BREAK_EXEC; 781 break; 782 case '1': /* hardware-breakpoint */ 783 wtype |= _DEBUG_BREAK_EXEC; 784 break; 785 case '2': /* write watchpoint */ 786 wtype |= _DEBUG_BREAK_RW; 787 break; 788 case '3': /* read watchpoint */ 789 wtype |= _DEBUG_BREAK_RD; 790 break; 791 case '4': /* access watchpoint */ 792 wtype |= _DEBUG_BREAK_RW; 793 break; 794 default: 795 return 1; /* Not supported. */ 796 } 797 return nto_breakpoint (addr, wtype, 0); 798} 799 800/* Remove {break/watch}point at address ADDR. 801 TYPE must be in '0'..'4' range. LEN is not used. */ 802 803static int 804nto_remove_point (char type, CORE_ADDR addr, int len) 805{ 806 int wtype = _DEBUG_BREAK_HW; /* Always request HW. */ 807 808 TRACE ("%s type:%c addr: 0x%08lx len:%d\n", __func__, (int)type, addr, len); 809 switch (type) 810 { 811 case '0': /* software-breakpoint */ 812 wtype = _DEBUG_BREAK_EXEC; 813 break; 814 case '1': /* hardware-breakpoint */ 815 wtype |= _DEBUG_BREAK_EXEC; 816 break; 817 case '2': /* write watchpoint */ 818 wtype |= _DEBUG_BREAK_RW; 819 break; 820 case '3': /* read watchpoint */ 821 wtype |= _DEBUG_BREAK_RD; 822 break; 823 case '4': /* access watchpoint */ 824 wtype |= _DEBUG_BREAK_RW; 825 break; 826 default: 827 return 1; /* Not supported. */ 828 } 829 return nto_breakpoint (addr, wtype, -1); 830} 831 832/* Check if the reason of stop for current thread (CURRENT_INFERIOR) is 833 a watchpoint. 834 835 Return 1 if stopped by watchpoint, 0 otherwise. */ 836 837static int 838nto_stopped_by_watchpoint (void) 839{ 840 int ret = 0; 841 842 TRACE ("%s\n", __func__); 843 if (nto_inferior.ctl_fd != -1 && current_inferior != NULL) 844 { 845 ptid_t ptid; 846 847 ptid = thread_to_gdb_id (current_inferior); 848 if (nto_set_thread (ptid)) 849 { 850 const int watchmask = _DEBUG_FLAG_TRACE_RD | _DEBUG_FLAG_TRACE_WR 851 | _DEBUG_FLAG_TRACE_MODIFY; 852 procfs_status status; 853 int err; 854 855 err = devctl (nto_inferior.ctl_fd, DCMD_PROC_STATUS, &status, 856 sizeof (status), 0); 857 if (err == EOK && (status.flags & watchmask)) 858 ret = 1; 859 } 860 } 861 TRACE ("%s: %s\n", __func__, ret ? "yes" : "no"); 862 return ret; 863} 864 865/* Get instruction pointer for CURRENT_INFERIOR thread. 866 867 Return inferior's instruction pointer value, or 0 on error. */ 868 869static CORE_ADDR 870nto_stopped_data_address (void) 871{ 872 CORE_ADDR ret = (CORE_ADDR)0; 873 874 TRACE ("%s\n", __func__); 875 if (nto_inferior.ctl_fd != -1 && current_inferior != NULL) 876 { 877 ptid_t ptid; 878 879 ptid = thread_to_gdb_id (current_inferior); 880 881 if (nto_set_thread (ptid)) 882 { 883 procfs_status status; 884 885 if (devctl (nto_inferior.ctl_fd, DCMD_PROC_STATUS, &status, 886 sizeof (status), 0) == EOK) 887 ret = status.ip; 888 } 889 } 890 TRACE ("%s: 0x%08lx\n", __func__, ret); 891 return ret; 892} 893 894/* We do not currently support non-stop. */ 895 896static int 897nto_supports_non_stop (void) 898{ 899 TRACE ("%s\n", __func__); 900 return 0; 901} 902 903 904 905static struct target_ops nto_target_ops = { 906 nto_create_inferior, 907 nto_attach, 908 nto_kill, 909 nto_detach, 910 nto_mourn, 911 NULL, /* nto_join */ 912 nto_thread_alive, 913 nto_resume, 914 nto_wait, 915 nto_fetch_registers, 916 nto_store_registers, 917 NULL, /* prepare_to_access_memory */ 918 NULL, /* done_accessing_memory */ 919 nto_read_memory, 920 nto_write_memory, 921 NULL, /* nto_look_up_symbols */ 922 nto_request_interrupt, 923 nto_read_auxv, 924 nto_insert_point, 925 nto_remove_point, 926 nto_stopped_by_watchpoint, 927 nto_stopped_data_address, 928 NULL, /* nto_read_offsets */ 929 NULL, /* thread_db_set_tls_address */ 930 NULL, 931 hostio_last_error_from_errno, 932 NULL, /* nto_qxfer_osdata */ 933 NULL, /* xfer_siginfo */ 934 nto_supports_non_stop, 935 NULL, /* async */ 936 NULL /* start_non_stop */ 937}; 938 939 940/* Global function called by server.c. Initializes QNX Neutrino 941 gdbserver. */ 942 943void 944initialize_low (void) 945{ 946 sigset_t set; 947 948 TRACE ("%s\n", __func__); 949 set_target_ops (&nto_target_ops); 950 set_breakpoint_data (the_low_target.breakpoint, 951 the_low_target.breakpoint_len); 952 953 /* We use SIGUSR1 to gain control after we block waiting for a process. 954 We use sigwaitevent to wait. */ 955 sigemptyset (&set); 956 sigaddset (&set, SIGUSR1); 957 sigprocmask (SIG_BLOCK, &set, NULL); 958} 959 960