util.c revision 1d08dcf46dd4b2cfe3e27723c05b0aec9955c591
1/* 2 * Copyright (c) 1991, 1992 Paul Kranenburg <pk@cs.few.eur.nl> 3 * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl> 4 * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com> 5 * Copyright (c) 1996-1999 Wichert Akkerman <wichert@cistron.nl> 6 * Copyright (c) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation 7 * Linux for s390 port by D.J. Barrow 8 * <barrow_dj@mail.yahoo.com,djbarrow@de.ibm.com> 9 * All rights reserved. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. The name of the author may not be used to endorse or promote products 20 * derived from this software without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 * 33 * $Id$ 34 */ 35 36#include "defs.h" 37 38#include <sys/user.h> 39#include <sys/param.h> 40#include <fcntl.h> 41#if HAVE_SYS_UIO_H 42#include <sys/uio.h> 43#endif 44#ifdef SUNOS4 45#include <machine/reg.h> 46#include <a.out.h> 47#include <link.h> 48#endif /* SUNOS4 */ 49 50#if defined(linux) && (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 1)) 51#include <linux/ptrace.h> 52#endif 53 54#if defined(LINUX) && defined(IA64) 55#include <asm/ptrace_offsets.h> 56#endif 57 58#ifdef HAVE_SYS_REG_H 59#include <sys/reg.h> 60# define PTRACE_PEEKUSR PTRACE_PEEKUSER 61#elif defined(HAVE_LINUX_PTRACE_H) 62#undef PTRACE_SYSCALL 63#include <linux/ptrace.h> 64#endif 65 66#ifdef SUNOS4_KERNEL_ARCH_KLUDGE 67#include <sys/utsname.h> 68#endif /* SUNOS4_KERNEL_ARCH_KLUDGE */ 69 70#if defined(LINUX) && defined(SPARC) 71 72#include <asm/reg.h> 73 74#if !defined(__GLIBC__) 75 76#include <linux/unistd.h> 77 78#define _hack_syscall5(type,name,type1,arg1,type2,arg2,type3,arg3,type4,arg4,\ 79 type5,arg5,syscall) \ 80type name (type1 arg1,type2 arg2,type3 arg3,type4 arg4,type5 arg5) \ 81{ \ 82 long __res; \ 83\ 84__asm__ volatile ("or %%g0, %1, %%o0\n\t" \ 85 "or %%g0, %2, %%o1\n\t" \ 86 "or %%g0, %3, %%o2\n\t" \ 87 "or %%g0, %4, %%o3\n\t" \ 88 "or %%g0, %5, %%o4\n\t" \ 89 "or %%g0, %6, %%g1\n\t" \ 90 "t 0x10\n\t" \ 91 "bcc 1f\n\t" \ 92 "or %%g0, %%o0, %0\n\t" \ 93 "sub %%g0, %%o0, %0\n\t" \ 94 "1:\n\t" \ 95 : "=r" (__res) \ 96 : "0" ((long)(arg1)),"1" ((long)(arg2)), \ 97 "2" ((long)(arg3)),"3" ((long)(arg4)),"4" ((long)(arg5)), \ 98 "i" (__NR_##syscall) \ 99 : "g1", "o0", "o1", "o2", "o3", "o4"); \ 100if (__res>=0) \ 101 return (type) __res; \ 102errno = -__res; \ 103return -1; \ 104} 105 106static _hack_syscall5(int,_ptrace,int,__request,int,__pid,int,__addr,int,__data,int,__addr2,ptrace) 107 108#define _ptrace 109 110#endif 111 112#endif 113 114/* macros */ 115#ifndef MAX 116#define MAX(a,b) (((a) > (b)) ? (a) : (b)) 117#endif 118#ifndef MIN 119#define MIN(a,b) (((a) < (b)) ? (a) : (b)) 120#endif 121 122void 123tv_tv(tv, a, b) 124struct timeval *tv; 125int a; 126int b; 127{ 128 tv->tv_sec = a; 129 tv->tv_usec = b; 130} 131 132int 133tv_nz(a) 134struct timeval *a; 135{ 136 return a->tv_sec || a->tv_usec; 137} 138 139int 140tv_cmp(a, b) 141struct timeval *a, *b; 142{ 143 if (a->tv_sec < b->tv_sec 144 || (a->tv_sec == b->tv_sec && a->tv_usec < b->tv_usec)) 145 return -1; 146 if (a->tv_sec > b->tv_sec 147 || (a->tv_sec == b->tv_sec && a->tv_usec > b->tv_usec)) 148 return 1; 149 return 0; 150} 151 152double 153tv_float(tv) 154struct timeval *tv; 155{ 156 return tv->tv_sec + tv->tv_usec/1000000.0; 157} 158 159void 160tv_add(tv, a, b) 161struct timeval *tv, *a, *b; 162{ 163 tv->tv_sec = a->tv_sec + b->tv_sec; 164 tv->tv_usec = a->tv_usec + b->tv_usec; 165 if (tv->tv_usec > 1000000) { 166 tv->tv_sec++; 167 tv->tv_usec -= 1000000; 168 } 169} 170 171void 172tv_sub(tv, a, b) 173struct timeval *tv, *a, *b; 174{ 175 tv->tv_sec = a->tv_sec - b->tv_sec; 176 tv->tv_usec = a->tv_usec - b->tv_usec; 177 if (((long) tv->tv_usec) < 0) { 178 tv->tv_sec--; 179 tv->tv_usec += 1000000; 180 } 181} 182 183void 184tv_div(tv, a, n) 185struct timeval *tv, *a; 186int n; 187{ 188 tv->tv_usec = (a->tv_sec % n * 1000000 + a->tv_usec + n / 2) / n; 189 tv->tv_sec = a->tv_sec / n + tv->tv_usec / 1000000; 190 tv->tv_usec %= 1000000; 191} 192 193void 194tv_mul(tv, a, n) 195struct timeval *tv, *a; 196int n; 197{ 198 tv->tv_usec = a->tv_usec * n; 199 tv->tv_sec = a->tv_sec * n + a->tv_usec / 1000000; 200 tv->tv_usec %= 1000000; 201} 202 203char * 204xlookup(xlat, val) 205struct xlat *xlat; 206int val; 207{ 208 for (; xlat->str != NULL; xlat++) 209 if (xlat->val == val) 210 return xlat->str; 211 return NULL; 212} 213 214/* 215 * Print entry in struct xlat table, if there. 216 */ 217void 218printxval(xlat, val, dflt) 219struct xlat *xlat; 220int val; 221char *dflt; 222{ 223 char *str = xlookup(xlat, val); 224 225 if (str) 226 tprintf("%s", str); 227 else 228 tprintf("%#x /* %s */", val, dflt); 229} 230 231/* 232 * Interpret `xlat' as an array of flags 233 * print the entries whose bits are on in `flags' 234 * return # of flags printed. 235 */ 236int 237addflags(xlat, flags) 238struct xlat *xlat; 239int flags; 240{ 241 int n; 242 243 for (n = 0; xlat->str; xlat++) { 244 if (xlat->val && (flags & xlat->val) == xlat->val) { 245 tprintf("|%s", xlat->str); 246 flags &= ~xlat->val; 247 n++; 248 } 249 } 250 if (flags) { 251 tprintf("|%#x", flags); 252 n++; 253 } 254 return n; 255} 256 257int 258printflags(xlat, flags) 259struct xlat *xlat; 260int flags; 261{ 262 int n; 263 char *sep; 264 265 if (flags == 0 && xlat->val == 0) { 266 tprintf("%s", xlat->str); 267 return 1; 268 } 269 270 sep = ""; 271 for (n = 0; xlat->str; xlat++) { 272 if (xlat->val && (flags & xlat->val) == xlat->val) { 273 tprintf("%s%s", sep, xlat->str); 274 flags &= ~xlat->val; 275 sep = "|"; 276 n++; 277 } 278 } 279 if (flags) { 280 tprintf("%s%#x", sep, flags); 281 n++; 282 } 283 return n; 284} 285 286void 287printnum(tcp, addr, fmt) 288struct tcb *tcp; 289long addr; 290char *fmt; 291{ 292 int num; 293 294 if (!addr) { 295 tprintf("NULL"); 296 return; 297 } 298 if (umove(tcp, addr, &num) < 0) { 299 tprintf("%#lx", addr); 300 return; 301 } 302 tprintf("["); 303 tprintf(fmt, num); 304 tprintf("]"); 305} 306 307static char path[MAXPATHLEN + 1]; 308 309void 310string_quote(str) 311char *str; 312{ 313 char buf[2 * MAXPATHLEN + 1]; 314 char *s; 315 316 if (!strpbrk(str, "\"\'\\")) { 317 tprintf("\"%s\"", str); 318 return; 319 } 320 for (s = buf; *str; str++) { 321 switch (*str) { 322 case '\"': case '\'': case '\\': 323 *s++ = '\\'; *s++ = *str; break; 324 default: 325 *s++ = *str; break; 326 } 327 } 328 *s = '\0'; 329 tprintf("\"%s\"", buf); 330} 331 332void 333printpath(tcp, addr) 334struct tcb *tcp; 335long addr; 336{ 337 if (umovestr(tcp, addr, MAXPATHLEN, path) < 0) 338 tprintf("%#lx", addr); 339 else 340 string_quote(path); 341 return; 342} 343 344void 345printpathn(tcp, addr, n) 346struct tcb *tcp; 347long addr; 348int n; 349{ 350 if (umovestr(tcp, addr, n, path) < 0) 351 tprintf("%#lx", addr); 352 else { 353 path[n] = '\0'; 354 string_quote(path); 355 } 356} 357 358void 359printstr(tcp, addr, len) 360struct tcb *tcp; 361long addr; 362int len; 363{ 364 static unsigned char *str = NULL; 365 static char *outstr; 366 int i, n, c, usehex; 367 char *s, *outend; 368 369 if (!addr) { 370 tprintf("NULL"); 371 return; 372 } 373 if (!str) { 374 if ((str = malloc(max_strlen)) == NULL 375 || (outstr = malloc(2*max_strlen)) == NULL) { 376 fprintf(stderr, "printstr: no memory\n"); 377 tprintf("%#lx", addr); 378 return; 379 } 380 } 381 outend = outstr + max_strlen * 2 - 10; 382 if (len < 0) { 383 n = max_strlen; 384 if (umovestr(tcp, addr, n, (char *) str) < 0) { 385 tprintf("%#lx", addr); 386 return; 387 } 388 } 389 else { 390 n = MIN(len, max_strlen); 391 if (umoven(tcp, addr, n, (char *) str) < 0) { 392 tprintf("%#lx", addr); 393 return; 394 } 395 } 396 397 usehex = 0; 398 if (xflag > 1) 399 usehex = 1; 400 else if (xflag) { 401 for (i = 0; i < n; i++) { 402 c = str[i]; 403 if (len < 0 && c == '\0') 404 break; 405 if (!isprint(c) && !isspace(c)) { 406 usehex = 1; 407 break; 408 } 409 } 410 } 411 412 s = outstr; 413 *s++ = '\"'; 414 415 if (usehex) { 416 for (i = 0; i < n; i++) { 417 c = str[i]; 418 if (len < 0 && c == '\0') 419 break; 420 sprintf(s, "\\x%02x", c); 421 s += 4; 422 if (s > outend) 423 break; 424 } 425 } 426 else { 427 for (i = 0; i < n; i++) { 428 c = str[i]; 429 if (len < 0 && c == '\0') 430 break; 431 switch (c) { 432 case '\"': case '\'': case '\\': 433 *s++ = '\\'; *s++ = c; break; 434 case '\f': 435 *s++ = '\\'; *s++ = 'f'; break; 436 case '\n': 437 *s++ = '\\'; *s++ = 'n'; break; 438 case '\r': 439 *s++ = '\\'; *s++ = 'r'; break; 440 case '\t': 441 *s++ = '\\'; *s++ = 't'; break; 442 case '\v': 443 *s++ = '\\'; *s++ = 'v'; break; 444 default: 445 if (isprint(c)) 446 *s++ = c; 447 else if (i < n - 1 && isdigit(str[i + 1])) { 448 sprintf(s, "\\%03o", c); 449 s += 4; 450 } 451 else { 452 sprintf(s, "\\%o", c); 453 s += strlen(s); 454 } 455 break; 456 } 457 if (s > outend) 458 break; 459 } 460 } 461 462 *s++ = '\"'; 463 if (i < len || (len < 0 && (i == n || s > outend))) { 464 *s++ = '.'; *s++ = '.'; *s++ = '.'; 465 } 466 *s = '\0'; 467 tprintf("%s", outstr); 468} 469 470#if HAVE_SYS_UIO_H 471void 472dumpiov(tcp, len, addr) 473struct tcb * tcp; 474int len; 475long addr; 476{ 477 struct iovec *iov; 478 int i; 479 480 481 if ((iov = (struct iovec *) malloc(len * sizeof *iov)) == NULL) { 482 fprintf(stderr, "dump: No memory"); 483 return; 484 } 485 if (umoven(tcp, addr, 486 len * sizeof *iov, (char *) iov) >= 0) { 487 488 for (i = 0; i < len; i++) { 489 /* include the buffer number to make it easy to 490 * match up the trace with the source */ 491 tprintf(" * %lu bytes in buffer %d\n", 492 (unsigned long)iov[i].iov_len, i); 493 dumpstr(tcp, (long) iov[i].iov_base, 494 iov[i].iov_len); 495 } 496 } 497 free((char *) iov); 498 499} 500#endif 501 502void 503dumpstr(tcp, addr, len) 504struct tcb *tcp; 505long addr; 506int len; 507{ 508 static int strsize = -1; 509 static unsigned char *str; 510 static char outstr[80]; 511 char *s; 512 int i, j; 513 514 if (strsize < len) { 515 if (str) 516 free(str); 517 if ((str = malloc(len)) == NULL) { 518 fprintf(stderr, "dump: no memory\n"); 519 return; 520 } 521 strsize = len; 522 } 523 524 if (umoven(tcp, addr, len, (char *) str) < 0) 525 return; 526 527 for (i = 0; i < len; i += 16) { 528 s = outstr; 529 sprintf(s, " | %05x ", i); 530 s += 9; 531 for (j = 0; j < 16; j++) { 532 if (j == 8) 533 *s++ = ' '; 534 if (i + j < len) { 535 sprintf(s, " %02x", str[i + j]); 536 s += 3; 537 } 538 else { 539 *s++ = ' '; *s++ = ' '; *s++ = ' '; 540 } 541 } 542 *s++ = ' '; *s++ = ' '; 543 for (j = 0; j < 16; j++) { 544 if (j == 8) 545 *s++ = ' '; 546 if (i + j < len) { 547 if (isprint(str[i + j])) 548 *s++ = str[i + j]; 549 else 550 *s++ = '.'; 551 } 552 else 553 *s++ = ' '; 554 } 555 tprintf("%s |\n", outstr); 556 } 557} 558 559#define PAGMASK (~(PAGSIZ - 1)) 560/* 561 * move `len' bytes of data from process `pid' 562 * at address `addr' to our space at `laddr' 563 */ 564int 565umoven(tcp, addr, len, laddr) 566struct tcb *tcp; 567long addr; 568int len; 569char *laddr; 570{ 571 572#ifdef LINUX 573 int pid = tcp->pid; 574 int n, m; 575 int started = 0; 576 union { 577 long val; 578 char x[sizeof(long)]; 579 } u; 580 581 if (addr & (sizeof(long) - 1)) { 582 /* addr not a multiple of sizeof(long) */ 583 n = addr - (addr & -sizeof(long)); /* residue */ 584 addr &= -sizeof(long); /* residue */ 585 errno = 0; 586 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0); 587 if (errno) { 588 if (started && (errno==EPERM || errno==EIO)) { 589 /* Ran into 'end of memory' - stupid "printpath" */ 590 return 0; 591 } 592 /* But if not started, we had a bogus address. */ 593 perror("ptrace: umoven"); 594 return -1; 595 } 596 started = 1; 597 memcpy(laddr, &u.x[n], m = MIN(sizeof(long) - n, len)); 598 addr += sizeof(long), laddr += m, len -= m; 599 } 600 while (len) { 601 errno = 0; 602 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0); 603 if (errno) { 604 if (started && (errno==EPERM || errno==EIO)) { 605 /* Ran into 'end of memory' - stupid "printpath" */ 606 return 0; 607 } 608 perror("ptrace: umoven"); 609 return -1; 610 } 611 started = 1; 612 memcpy(laddr, u.x, m = MIN(sizeof(long), len)); 613 addr += sizeof(long), laddr += m, len -= m; 614 } 615#endif /* LINUX */ 616 617#ifdef SUNOS4 618 int pid = tcp->pid; 619#if 0 620 int n, m; 621 union { 622 long val; 623 char x[sizeof(long)]; 624 } u; 625 626 if (addr & (sizeof(long) - 1)) { 627 /* addr not a multiple of sizeof(long) */ 628 n = addr - (addr & -sizeof(long)); /* residue */ 629 addr &= -sizeof(long); /* residue */ 630 errno = 0; 631 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0); 632 if (errno) { 633 perror("umoven"); 634 return -1; 635 } 636 memcpy(laddr, &u.x[n], m = MIN(sizeof(long) - n, len)); 637 addr += sizeof(long), laddr += m, len -= m; 638 } 639 while (len) { 640 errno = 0; 641 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *) addr, 0); 642 if (errno) { 643 perror("umoven"); 644 return -1; 645 } 646 memcpy(laddr, u.x, m = MIN(sizeof(long), len)); 647 addr += sizeof(long), laddr += m, len -= m; 648 } 649#else /* !oldway */ 650 int n; 651 652 while (len) { 653 n = MIN(len, PAGSIZ); 654 n = MIN(n, ((addr + PAGSIZ) & PAGMASK) - addr); 655 if (ptrace(PTRACE_READDATA, pid, 656 (char *) addr, len, laddr) < 0) { 657 perror("umoven: ptrace(PTRACE_READDATA, ...)"); 658 abort(); 659 return -1; 660 } 661 len -= n; 662 addr += n; 663 laddr += n; 664 } 665#endif /* !oldway */ 666#endif /* SUNOS4 */ 667 668#ifdef USE_PROCFS 669#ifdef HAVE_MP_PROCFS 670 int fd = tcp->pfd_as; 671#else 672 int fd = tcp->pfd; 673#endif 674 lseek(fd, addr, SEEK_SET); 675 if (read(fd, laddr, len) == -1) 676 return -1; 677#endif /* USE_PROCFS */ 678 679 return 0; 680} 681 682/* 683 * like `umove' but make the additional effort of looking 684 * for a terminating zero byte. 685 */ 686int 687umovestr(tcp, addr, len, laddr) 688struct tcb *tcp; 689long addr; 690int len; 691char *laddr; 692{ 693#ifdef USE_PROCFS 694#ifdef HAVE_MP_PROCFS 695 int fd = tcp->pfd_as; 696#else 697 int fd = tcp->pfd; 698#endif 699 /* Some systems (e.g. FreeBSD) can be upset if we read off the 700 end of valid memory, avoid this by trying to read up 701 to page boundaries. But we don't know what a page is (and 702 getpagesize(2) (if it exists) doesn't necessarily return 703 hardware page size). Assume all pages >= 1024 (a-historical 704 I know) */ 705 706 int page = 1024; /* How to find this? */ 707 int move = page - (addr & (page - 1)); 708 int left = len; 709 710 lseek(fd, addr, SEEK_SET); 711 712 while (left) { 713 if (move > left) move = left; 714 if ((move = read(fd, laddr, move)) == -1) 715 return left != len ? 0 : -1; 716 if (memchr (laddr, 0, move)) break; 717 left -= move; 718 laddr += move; 719 addr += move; 720 move = page; 721 } 722#else /* !USE_PROCFS */ 723 int started = 0; 724 int pid = tcp->pid; 725 int i, n, m; 726 union { 727 long val; 728 char x[sizeof(long)]; 729 } u; 730 731 if (addr & (sizeof(long) - 1)) { 732 /* addr not a multiple of sizeof(long) */ 733 n = addr - (addr & -sizeof(long)); /* residue */ 734 addr &= -sizeof(long); /* residue */ 735 errno = 0; 736 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0); 737 if (errno) { 738 if (started && (errno==EPERM || errno==EIO)) { 739 /* Ran into 'end of memory' - stupid "printpath" */ 740 return 0; 741 } 742 perror("umovestr"); 743 return -1; 744 } 745 started = 1; 746 memcpy(laddr, &u.x[n], m = MIN(sizeof(long)-n,len)); 747 while (n & (sizeof(long) - 1)) 748 if (u.x[n++] == '\0') 749 return 0; 750 addr += sizeof(long), laddr += m, len -= m; 751 } 752 while (len) { 753 errno = 0; 754 u.val = ptrace(PTRACE_PEEKDATA, pid, (char *)addr, 0); 755 if (errno) { 756 if (started && (errno==EPERM || errno==EIO)) { 757 /* Ran into 'end of memory' - stupid "printpath" */ 758 return 0; 759 } 760 perror("umovestr"); 761 return -1; 762 } 763 started = 1; 764 memcpy(laddr, u.x, m = MIN(sizeof(long), len)); 765 for (i = 0; i < sizeof(long); i++) 766 if (u.x[i] == '\0') 767 return 0; 768 769 addr += sizeof(long), laddr += m, len -= m; 770 } 771#endif /* !USE_PROCFS */ 772 return 0; 773} 774 775#ifdef LINUX 776#ifndef SPARC 777#define PTRACE_WRITETEXT 101 778#define PTRACE_WRITEDATA 102 779#endif /* !SPARC */ 780#endif /* LINUX */ 781 782#ifdef SUNOS4 783 784static int 785uload(cmd, pid, addr, len, laddr) 786int cmd; 787int pid; 788long addr; 789int len; 790char *laddr; 791{ 792#if 0 793 int n; 794 795 while (len) { 796 n = MIN(len, PAGSIZ); 797 n = MIN(n, ((addr + PAGSIZ) & PAGMASK) - addr); 798 if (ptrace(cmd, pid, (char *)addr, n, laddr) < 0) { 799 perror("uload: ptrace(PTRACE_WRITE, ...)"); 800 return -1; 801 } 802 len -= n; 803 addr += n; 804 laddr += n; 805 } 806#else 807 int peek, poke; 808 int n, m; 809 union { 810 long val; 811 char x[sizeof(long)]; 812 } u; 813 814 if (cmd == PTRACE_WRITETEXT) { 815 peek = PTRACE_PEEKTEXT; 816 poke = PTRACE_POKETEXT; 817 } 818 else { 819 peek = PTRACE_PEEKDATA; 820 poke = PTRACE_POKEDATA; 821 } 822 if (addr & (sizeof(long) - 1)) { 823 /* addr not a multiple of sizeof(long) */ 824 n = addr - (addr & -sizeof(long)); /* residue */ 825 addr &= -sizeof(long); 826 errno = 0; 827 u.val = ptrace(peek, pid, (char *) addr, 0); 828 if (errno) { 829 perror("uload: POKE"); 830 return -1; 831 } 832 memcpy(&u.x[n], laddr, m = MIN(sizeof(long) - n, len)); 833 if (ptrace(poke, pid, (char *)addr, u.val) < 0) { 834 perror("uload: POKE"); 835 return -1; 836 } 837 addr += sizeof(long), laddr += m, len -= m; 838 } 839 while (len) { 840 if (len < sizeof(long)) 841 u.val = ptrace(peek, pid, (char *) addr, 0); 842 memcpy(u.x, laddr, m = MIN(sizeof(long), len)); 843 if (ptrace(poke, pid, (char *) addr, u.val) < 0) { 844 perror("uload: POKE"); 845 return -1; 846 } 847 addr += sizeof(long), laddr += m, len -= m; 848 } 849#endif 850 return 0; 851} 852 853int 854tload(pid, addr, len, laddr) 855int pid; 856int addr, len; 857char *laddr; 858{ 859 return uload(PTRACE_WRITETEXT, pid, addr, len, laddr); 860} 861 862int 863dload(pid, addr, len, laddr) 864int pid; 865int addr; 866int len; 867char *laddr; 868{ 869 return uload(PTRACE_WRITEDATA, pid, addr, len, laddr); 870} 871 872#endif /* SUNOS4 */ 873 874#ifndef USE_PROCFS 875 876int 877upeek(pid, off, res) 878int pid; 879long off; 880long *res; 881{ 882 long val; 883 884#ifdef SUNOS4_KERNEL_ARCH_KLUDGE 885 { 886 static int is_sun4m = -1; 887 struct utsname name; 888 889 /* Round up the usual suspects. */ 890 if (is_sun4m == -1) { 891 if (uname(&name) < 0) { 892 perror("upeek: uname?"); 893 exit(1); 894 } 895 is_sun4m = strcmp(name.machine, "sun4m") == 0; 896 if (is_sun4m) { 897 extern struct xlat struct_user_offsets[]; 898 struct xlat *x; 899 900 for (x = struct_user_offsets; x->str; x++) 901 x->val += 1024; 902 } 903 } 904 if (is_sun4m) 905 off += 1024; 906 } 907#endif /* SUNOS4_KERNEL_ARCH_KLUDGE */ 908 errno = 0; 909 val = ptrace(PTRACE_PEEKUSER, pid, (char *) off, 0); 910 if (val == -1 && errno) { 911 perror("upeek: ptrace(PTRACE_PEEKUSER, ... )"); 912 return -1; 913 } 914 *res = val; 915 return 0; 916} 917 918#endif /* !USE_PROCFS */ 919 920long 921getpc(tcp) 922struct tcb *tcp; 923{ 924 925#ifdef LINUX 926 long pc; 927#if defined(I386) 928 if (upeek(tcp->pid, 4*EIP, &pc) < 0) 929 return -1; 930#elif defined(IA64) 931 if (upeek(tcp->pid, PT_B0, &pc) < 0) 932 return -1; 933#elif defined(ARM) 934 if (upeek(tcp->pid, 4*15, &pc) < 0) 935 return -1; 936#elif defined(POWERPC) 937 if (upeek(tcp->pid, 4*PT_NIP, &pc) < 0) 938 return -1; 939#elif defined(M68k) 940 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0) 941 return -1; 942#elif defined(ALPHA) 943 if (upeek(tcp->pid, REG_PC, &pc) < 0) 944 return -1; 945#elif defined(MIPS) 946 if (upeek(tcp->pid, REG_EPC, &pc) < 0) 947 return -1; 948#elif defined(SPARC) 949 struct regs regs; 950 if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)®s,0) < 0) 951 return -1; 952 pc = regs.r_pc; 953#elif defined(S390) 954 if(upeek(tcp->pid,PT_PSWADDR,&pc) < 0) 955#elif defined(HPPA) 956 if(upeek(tcp->pid,PT_IAOQ0,&pc) < 0) 957 return -1; 958#endif 959 return pc; 960#endif /* LINUX */ 961 962#ifdef SUNOS4 963 /* 964 * Return current program counter for `pid' 965 * Assumes PC is never 0xffffffff 966 */ 967 struct regs regs; 968 969 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *) ®s, 0) < 0) { 970 perror("getpc: ptrace(PTRACE_GETREGS, ...)"); 971 return -1; 972 } 973 return regs.r_pc; 974#endif /* SUNOS4 */ 975 976#ifdef SVR4 977 /* XXX */ 978 return 0; 979#endif /* SVR4 */ 980 981#ifdef FREEBSD 982 struct reg regs; 983 pread(tcp->pfd_reg, ®s, sizeof(regs), 0); 984 return regs.r_eip; 985#endif /* FREEBSD */ 986} 987 988void 989printcall(tcp) 990struct tcb *tcp; 991{ 992 993#ifdef LINUX 994#ifdef I386 995 long eip; 996 997 if (upeek(tcp->pid, 4*EIP, &eip) < 0) { 998 tprintf("[????????] "); 999 return; 1000 } 1001 tprintf("[%08lx] ", eip); 1002#elif defined(IA62) 1003 long ip; 1004 1005 if (upeek(tcp->pid, PT_B0, &ip) < 0) { 1006 tprintf("[????????] "); 1007 return; 1008 } 1009 tprintf("[%08lx] ", ip); 1010#elif defined(POWERPC) 1011 long pc; 1012 1013 if (upeek(tcp->pid, 4*PT_NIP, &pc) < 0) { 1014 tprintf ("[????????] "); 1015 return; 1016 } 1017 tprintf("[%08lx] ", pc); 1018#elif defined(M68k) 1019 long pc; 1020 1021 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0) { 1022 tprintf ("[????????] "); 1023 return; 1024 } 1025 tprintf("[%08lx] ", pc); 1026#elif defined(ALPHA) 1027 long pc; 1028 1029 if (upeek(tcp->pid, REG_PC, &pc) < 0) { 1030 tprintf ("[????????] "); 1031 return; 1032 } 1033 tprintf("[%08lx] ", pc); 1034#elif defined(SPARC) 1035 struct regs regs; 1036 if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)®s,0) < 0) { 1037 tprintf("[????????] "); 1038 return; 1039 } 1040 tprintf("[%08lx] ", regs.r_pc); 1041#elif defined(HPPA) 1042 long pc; 1043 1044 if(upeek(tcp->pid,PT_IAOQ0,&pc) < 0) { 1045 tprintf ("[????????] "); 1046 return; 1047 } 1048 tprintf("[%08lx] ", pc); 1049#elif defined(MIPS) 1050 long pc; 1051 1052 if (upeek(tcp->pid, REG_EPC, &pc) < 0) { 1053 tprintf ("[????????] "); 1054 return; 1055 } 1056 tprintf("[%08lx] ", pc); 1057#endif /* !architecture */ 1058#endif /* LINUX */ 1059 1060#ifdef SUNOS4 1061 struct regs regs; 1062 1063 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *) ®s, 0) < 0) { 1064 perror("printcall: ptrace(PTRACE_GETREGS, ...)"); 1065 tprintf("[????????] "); 1066 return; 1067 } 1068 tprintf("[%08x] ", regs.r_o7); 1069#endif /* SUNOS4 */ 1070 1071#ifdef SVR4 1072 /* XXX */ 1073 tprintf("[????????] "); 1074#endif 1075 1076#ifdef FREEBSD 1077 struct reg regs; 1078 pread(tcp->pfd_reg, ®s, sizeof(regs), 0); 1079 tprintf("[%08x] ", regs.r_eip); 1080#endif /* FREEBSD */ 1081} 1082 1083#ifndef USE_PROCFS 1084 1085int 1086setbpt(tcp) 1087struct tcb *tcp; 1088{ 1089 1090#ifdef LINUX 1091#ifdef SPARC 1092 /* We simply use the SunOS breakpoint code. */ 1093 1094 struct regs regs; 1095#define LOOPA 0x30800000 /* ba,a 0 */ 1096 1097 if (tcp->flags & TCB_BPTSET) { 1098 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid); 1099 return -1; 1100 } 1101 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)®s, 0) < 0) { 1102 perror("setbpt: ptrace(PTRACE_GETREGS, ...)"); 1103 return -1; 1104 } 1105 tcp->baddr = regs.r_o7 + 8; 1106 errno = 0; 1107 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)tcp->baddr, 0); 1108 if(errno) { 1109 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)"); 1110 return -1; 1111 } 1112 1113 /* 1114 * XXX - BRUTAL MODE ON 1115 * We cannot set a real BPT in the child, since it will not be 1116 * traced at the moment it will reach the trap and would probably 1117 * die with a core dump. 1118 * Thus, we are force our way in by taking out two instructions 1119 * and insert an eternal loop instead, in expectance of the SIGSTOP 1120 * generated by out PTRACE_ATTACH. 1121 * Of cause, if we evaporate ourselves in the middle of all this... 1122 */ 1123 errno = 0; 1124 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOPA); 1125 if(errno) { 1126 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)"); 1127 return -1; 1128 } 1129 tcp->flags |= TCB_BPTSET; 1130 1131#else /* !SPARC */ 1132#ifdef IA64 1133 /* 1134 * Our strategy here is to replace the bundle that contained 1135 * the clone() syscall with a bundle of the form: 1136 * 1137 * { 1: br 1b; br 1b; br 1b } 1138 * 1139 * This ensures that the newly forked child will loop 1140 * endlessly until we've got a chance to attach to it. 1141 */ 1142 { 1143# define LOOP0 0x0000100000000017 1144# define LOOP1 0x4000000000200000 1145 unsigned long addr, ipsr; 1146 pid_t pid; 1147 1148 pid = tcp->pid; 1149 if (upeek(pid, PT_CR_IPSR, &ipsr) < 0) 1150 return -1; 1151 if (upeek(pid, PT_CR_IIP, &addr) < 0) 1152 return -1; 1153 tcp->baddr = addr | ((ipsr >> 41) & 0x3); /* store "ri" in low two bits */ 1154 1155 errno = 0; 1156 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 0, 0); 1157 tcp->inst[1] = ptrace(PTRACE_PEEKTEXT, pid, (char *) addr + 8, 0); 1158 if (errno) { 1159 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)"); 1160 return -1; 1161 } 1162 1163 errno = 0; 1164 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, LOOP0); 1165 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, LOOP1); 1166 if (errno) { 1167 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)"); 1168 return -1; 1169 } 1170 tcp->flags |= TCB_BPTSET; 1171 } 1172#else /* !IA64 */ 1173 1174#if defined (I386) 1175#define LOOP 0x0000feeb 1176#elif defined (M68K) 1177#define LOOP 0x60fe0000 1178#elif defined (ALPHA) 1179#define LOOP 0xc3ffffff 1180#elif defined (POWERPC) 1181#define LOOP 0x0000feeb 1182#elif defined(ARM) 1183#define LOOP 0xEAFFFFFE 1184#elif defined(MIPS) 1185#define LOOP 0x1000ffff 1186#elif defined(S390) 1187#define LOOP 0xa7f40000 /* BRC 15,0 */ 1188#elif defined(HPPA) 1189#define LOOP 0xe81f1ff7 /* b,l,n <loc>,r0 */ 1190#else 1191#error unknown architecture 1192#endif 1193 1194 if (tcp->flags & TCB_BPTSET) { 1195 fprintf(stderr, "PANIC: bpt already set in pid %u\n", tcp->pid); 1196 return -1; 1197 } 1198#if defined (I386) 1199 if (upeek(tcp->pid, 4*EIP, &tcp->baddr) < 0) 1200 return -1; 1201#elif defined (M68K) 1202 if (upeek(tcp->pid, 4*PT_PC, &tcp->baddr) < 0) 1203 return -1; 1204#elif defined (ALPHA) 1205 return -1; 1206#elif defined (ARM) 1207 return -1; 1208#elif defined (MIPS) 1209 return -1; /* FIXME: I do not know what i do - Flo */ 1210#elif defined (POWERPC) 1211 if (upeek(tcp->pid, 4*PT_NIP, &tcp->baddr) < 0) 1212 return -1; 1213#elif defined(S390) 1214 if (upeek(tcp->pid,PT_PSWADDR, &tcp->baddr) < 0) 1215 return -1; 1216#elif defined(HPPA) 1217 if (upeek(tcp->pid, PT_IAOQ0, &tcp->baddr) < 0) 1218 return -1; 1219 tcp->baddr &= ~0x03; 1220#else 1221#error unknown architecture 1222#endif 1223 if (debug) 1224 fprintf(stderr, "[%d] setting bpt at %lx\n", tcp->pid, tcp->baddr); 1225 tcp->inst[0] = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *) tcp->baddr, 0); 1226 if (errno) { 1227 perror("setbpt: ptrace(PTRACE_PEEKTEXT, ...)"); 1228 return -1; 1229 } 1230 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, LOOP); 1231 if (errno) { 1232 perror("setbpt: ptrace(PTRACE_POKETEXT, ...)"); 1233 return -1; 1234 } 1235 tcp->flags |= TCB_BPTSET; 1236 1237#endif /* !IA64 */ 1238#endif /* SPARC */ 1239#endif /* LINUX */ 1240 1241#ifdef SUNOS4 1242#ifdef SPARC /* This code is slightly sparc specific */ 1243 1244 struct regs regs; 1245#define BPT 0x91d02001 /* ta 1 */ 1246#define LOOP 0x10800000 /* ba 0 */ 1247#define LOOPA 0x30800000 /* ba,a 0 */ 1248#define NOP 0x01000000 1249#if LOOPA 1250 static int loopdeloop[1] = {LOOPA}; 1251#else 1252 static int loopdeloop[2] = {LOOP, NOP}; 1253#endif 1254 1255 if (tcp->flags & TCB_BPTSET) { 1256 fprintf(stderr, "PANIC: TCB already set in pid %u\n", tcp->pid); 1257 return -1; 1258 } 1259 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)®s, 0) < 0) { 1260 perror("setbpt: ptrace(PTRACE_GETREGS, ...)"); 1261 return -1; 1262 } 1263 tcp->baddr = regs.r_o7 + 8; 1264 if (ptrace(PTRACE_READTEXT, tcp->pid, (char *)tcp->baddr, 1265 sizeof tcp->inst, (char *)tcp->inst) < 0) { 1266 perror("setbpt: ptrace(PTRACE_READTEXT, ...)"); 1267 return -1; 1268 } 1269 1270 /* 1271 * XXX - BRUTAL MODE ON 1272 * We cannot set a real BPT in the child, since it will not be 1273 * traced at the moment it will reach the trap and would probably 1274 * die with a core dump. 1275 * Thus, we are force our way in by taking out two instructions 1276 * and insert an eternal loop in stead, in expectance of the SIGSTOP 1277 * generated by out PTRACE_ATTACH. 1278 * Of cause, if we evaporate ourselves in the middle of all this... 1279 */ 1280 if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr, 1281 sizeof loopdeloop, (char *) loopdeloop) < 0) { 1282 perror("setbpt: ptrace(PTRACE_WRITETEXT, ...)"); 1283 return -1; 1284 } 1285 tcp->flags |= TCB_BPTSET; 1286 1287#endif /* SPARC */ 1288#endif /* SUNOS4 */ 1289 1290 return 0; 1291} 1292 1293int 1294clearbpt(tcp) 1295struct tcb *tcp; 1296{ 1297 1298#ifdef LINUX 1299#if defined(I386) 1300 long eip; 1301#elif defined(POWERPC) 1302 long pc; 1303#elif defined(M68K) 1304 long pc; 1305#elif defined(ALPHA) 1306 long pc; 1307#elif defined(HPPA) 1308 long iaoq; 1309#endif /* architecture */ 1310 1311#ifdef SPARC 1312 /* Again, we borrow the SunOS breakpoint code. */ 1313 if (!(tcp->flags & TCB_BPTSET)) { 1314 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid); 1315 return -1; 1316 } 1317 errno = 0; 1318 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]); 1319 if(errno) { 1320 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)"); 1321 return -1; 1322 } 1323 tcp->flags &= ~TCB_BPTSET; 1324#elif defined(IA64) 1325 { 1326 unsigned long addr, ipsr; 1327 pid_t pid; 1328 1329 pid = tcp->pid; 1330 1331 if (upeek(pid, PT_CR_IPSR, &ipsr) < 0) 1332 return -1; 1333 if (upeek(pid, PT_CR_IIP, &addr) < 0) 1334 return -1; 1335 1336 /* restore original bundle: */ 1337 errno = 0; 1338 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 0, tcp->inst[0]); 1339 ptrace(PTRACE_POKETEXT, pid, (char *) addr + 8, tcp->inst[1]); 1340 if (errno) { 1341 perror("clearbpt: ptrace(PTRACE_POKETEXT, ...)"); 1342 return -1; 1343 } 1344 1345 /* restore original "ri" in ipsr: */ 1346 ipsr = (ipsr & ~(0x3ul << 41)) | ((tcp->baddr & 0x3) << 41); 1347 errno = 0; 1348 ptrace(PTRACE_POKEUSER, pid, (char *) PT_CR_IPSR, ipsr); 1349 if (errno) { 1350 perror("clrbpt: ptrace(PTRACE_POKEUSER, ...)"); 1351 return -1; 1352 } 1353 1354 tcp->flags &= ~TCB_BPTSET; 1355 1356 if (addr != (tcp->baddr & ~0x3)) { 1357 /* the breakpoint has not been reached yet. */ 1358 if (debug) 1359 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n", 1360 addr, tcp->baddr); 1361 return 0; 1362 } 1363 } 1364#else /* !IA64 && ! SPARC */ 1365 1366 if (debug) 1367 fprintf(stderr, "[%d] clearing bpt\n", tcp->pid); 1368 if (!(tcp->flags & TCB_BPTSET)) { 1369 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid); 1370 return -1; 1371 } 1372 errno = 0; 1373 ptrace(PTRACE_POKETEXT, tcp->pid, (char *) tcp->baddr, tcp->inst[0]); 1374 if (errno) { 1375 perror("clearbtp: ptrace(PTRACE_POKETEXT, ...)"); 1376 return -1; 1377 } 1378 tcp->flags &= ~TCB_BPTSET; 1379 1380#ifdef I386 1381 if (upeek(tcp->pid, 4*EIP, &eip) < 0) 1382 return -1; 1383 if (eip != tcp->baddr) { 1384 /* The breakpoint has not been reached yet. */ 1385 if (debug) 1386 fprintf(stderr, 1387 "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n", 1388 eip, tcp->baddr); 1389 return 0; 1390 } 1391#elif defined(POWERPC) 1392 if (upeek(tcp->pid, 4*PT_NIP, &pc) < 0) 1393 return -1; 1394 if (pc != tcp->baddr) { 1395 /* The breakpoint has not been reached yet. */ 1396 if (debug) 1397 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n", 1398 pc, tcp->baddr); 1399 return 0; 1400 } 1401#elif defined(M68K) 1402 if (upeek(tcp->pid, 4*PT_PC, &pc) < 0) 1403 return -1; 1404 if (pc != tcp->baddr) { 1405 /* The breakpoint has not been reached yet. */ 1406 if (debug) 1407 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n", 1408 pc, tcp->baddr); 1409 return 0; 1410 } 1411#elif defined(ALPHA) 1412 if (upeek(tcp->pid, REG_PC, &pc) < 0) 1413 return -1; 1414 if (pc != tcp->baddr) { 1415 /* The breakpoint has not been reached yet. */ 1416 if (debug) 1417 fprintf(stderr, "NOTE: PC not at bpt (pc %#lx baddr %#lx)\n", 1418 pc, tcp->baddr); 1419 return 0; 1420 } 1421#elif defined(HPPA) 1422 if (upeek(tcp->pid, PT_IAOQ0, &iaoq) < 0) 1423 return -1; 1424 iaoq &= ~0x03; 1425 if (iaoq != tcp->baddr && iaoq != tcp->baddr + 4) { 1426 /* The breakpoint has not been reached yet. */ 1427 if (debug) 1428 fprintf(stderr, "NOTE: PC not at bpt (iaoq %#lx baddr %#lx)\n", 1429 iaoq, tcp->baddr); 1430 return 0; 1431 } 1432 iaoq = tcp->baddr | 3; 1433 /* We should be pointing at a 'ldi -1000,r1' in glibc, so it is 1434 * safe to set both IAOQ0 and IAOQ1 to that so the PSW N bit 1435 * has no significant effect. 1436 */ 1437 ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ0, iaoq); 1438 ptrace(PTRACE_POKEUSER, tcp->pid, (void *)PT_IAOQ1, iaoq); 1439#endif /* arch */ 1440#endif /* !SPARC && !IA64 */ 1441#endif /* LINUX */ 1442 1443#ifdef SUNOS4 1444#ifdef SPARC 1445 1446#if !LOOPA 1447 struct regs regs; 1448#endif 1449 1450 if (!(tcp->flags & TCB_BPTSET)) { 1451 fprintf(stderr, "PANIC: TCB not set in pid %u\n", tcp->pid); 1452 return -1; 1453 } 1454 if (ptrace(PTRACE_WRITETEXT, tcp->pid, (char *) tcp->baddr, 1455 sizeof tcp->inst, (char *) tcp->inst) < 0) { 1456 perror("clearbtp: ptrace(PTRACE_WRITETEXT, ...)"); 1457 return -1; 1458 } 1459 tcp->flags &= ~TCB_BPTSET; 1460 1461#if !LOOPA 1462 /* 1463 * Since we don't have a single instruction breakpoint, we may have 1464 * to adjust the program counter after removing the our `breakpoint'. 1465 */ 1466 if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)®s, 0) < 0) { 1467 perror("clearbpt: ptrace(PTRACE_GETREGS, ...)"); 1468 return -1; 1469 } 1470 if ((regs.r_pc < tcp->baddr) || 1471 (regs.r_pc > tcp->baddr + 4)) { 1472 /* The breakpoint has not been reached yet */ 1473 if (debug) 1474 fprintf(stderr, 1475 "NOTE: PC not at bpt (pc %#x baddr %#x)\n", 1476 regs.r_pc, tcp->parent->baddr); 1477 return 0; 1478 } 1479 if (regs.r_pc != tcp->baddr) 1480 if (debug) 1481 fprintf(stderr, "NOTE: PC adjusted (%#x -> %#x\n", 1482 regs.r_pc, tcp->baddr); 1483 1484 regs.r_pc = tcp->baddr; 1485 if (ptrace(PTRACE_SETREGS, tcp->pid, (char *)®s, 0) < 0) { 1486 perror("clearbpt: ptrace(PTRACE_SETREGS, ...)"); 1487 return -1; 1488 } 1489#endif /* LOOPA */ 1490#endif /* SPARC */ 1491#endif /* SUNOS4 */ 1492 1493 return 0; 1494} 1495 1496#endif /* !USE_PROCFS */ 1497 1498#ifdef SUNOS4 1499 1500static int 1501getex(pid, hdr) 1502int pid; 1503struct exec *hdr; 1504{ 1505 int n; 1506 1507 for (n = 0; n < sizeof *hdr; n += 4) { 1508 long res; 1509 if (upeek(pid, uoff(u_exdata) + n, &res) < 0) 1510 return -1; 1511 memcpy(((char *) hdr) + n, &res, 4); 1512 } 1513 if (debug) { 1514 fprintf(stderr, "[struct exec: magic: %o version %u Mach %o\n", 1515 hdr->a_magic, hdr->a_toolversion, hdr->a_machtype); 1516 fprintf(stderr, "Text %lu Data %lu Bss %lu Syms %lu Entry %#lx]\n", 1517 hdr->a_text, hdr->a_data, hdr->a_bss, hdr->a_syms, hdr->a_entry); 1518 } 1519 return 0; 1520} 1521 1522int 1523fixvfork(tcp) 1524struct tcb *tcp; 1525{ 1526 int pid = tcp->pid; 1527 /* 1528 * Change `vfork' in a freshly exec'ed dynamically linked 1529 * executable's (internal) symbol table to plain old `fork' 1530 */ 1531 1532 struct exec hdr; 1533 struct link_dynamic dyn; 1534 struct link_dynamic_2 ld; 1535 char *strtab, *cp; 1536 1537 if (getex(pid, &hdr) < 0) 1538 return -1; 1539 if (!hdr.a_dynamic) 1540 return -1; 1541 1542 if (umove(tcp, (int) N_DATADDR(hdr), &dyn) < 0) { 1543 fprintf(stderr, "Cannot read DYNAMIC\n"); 1544 return -1; 1545 } 1546 if (umove(tcp, (int) dyn.ld_un.ld_2, &ld) < 0) { 1547 fprintf(stderr, "Cannot read link_dynamic_2\n"); 1548 return -1; 1549 } 1550 if ((strtab = malloc((unsigned)ld.ld_symb_size)) == NULL) { 1551 fprintf(stderr, "fixvfork: out of memory\n"); 1552 return -1; 1553 } 1554 if (umoven(tcp, (int)ld.ld_symbols+(int)N_TXTADDR(hdr), 1555 (int)ld.ld_symb_size, strtab) < 0) 1556 goto err; 1557 1558#if 0 1559 for (cp = strtab; cp < strtab + ld.ld_symb_size; ) { 1560 fprintf(stderr, "[symbol: %s]\n", cp); 1561 cp += strlen(cp)+1; 1562 } 1563 return 0; 1564#endif 1565 for (cp = strtab; cp < strtab + ld.ld_symb_size; ) { 1566 if (strcmp(cp, "_vfork") == 0) { 1567 if (debug) 1568 fprintf(stderr, "fixvfork: FOUND _vfork\n"); 1569 strcpy(cp, "_fork"); 1570 break; 1571 } 1572 cp += strlen(cp)+1; 1573 } 1574 if (cp < strtab + ld.ld_symb_size) 1575 /* 1576 * Write entire symbol table back to avoid 1577 * memory alignment bugs in ptrace 1578 */ 1579 if (tload(pid, (int)ld.ld_symbols+(int)N_TXTADDR(hdr), 1580 (int)ld.ld_symb_size, strtab) < 0) 1581 goto err; 1582 1583 free(strtab); 1584 return 0; 1585 1586err: 1587 free(strtab); 1588 return -1; 1589} 1590 1591#endif /* SUNOS4 */ 1592