1e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata/* 2e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * This file is part of ltrace. 3e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * Copyright (C) 2004,2008,2009 Juan Cespedes 4e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * Copyright (C) 2006 Ian Wienand 5e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * 6e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * This program is free software; you can redistribute it and/or 7e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * modify it under the terms of the GNU General Public License as 8e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * published by the Free Software Foundation; either version 2 of the 9e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * License, or (at your option) any later version. 10e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * 11e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * This program is distributed in the hope that it will be useful, but 12e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * WITHOUT ANY WARRANTY; without even the implied warranty of 13e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * General Public License for more details. 15e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * 16e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * You should have received a copy of the GNU General Public License 17e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * along with this program; if not, write to the Free Software 18e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 19e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata * 02110-1301 USA 20e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata */ 21e99af270a60891e68d465c4cd97dbe29cd1a05e4Petr Machata 225c3fe0697b202cc7d95e90459de0fb312b297b27Juan Cespedes#include "config.h" 235c3fe0697b202cc7d95e90459de0fb312b297b27Juan Cespedes 245c3fe0697b202cc7d95e90459de0fb312b297b27Juan Cespedes#include <stdlib.h> 255c3fe0697b202cc7d95e90459de0fb312b297b27Juan Cespedes#include <sys/types.h> 265c3fe0697b202cc7d95e90459de0fb312b297b27Juan Cespedes#include <sys/wait.h> 275c3fe0697b202cc7d95e90459de0fb312b297b27Juan Cespedes#include <signal.h> 285c3fe0697b202cc7d95e90459de0fb312b297b27Juan Cespedes#include <string.h> 295c3fe0697b202cc7d95e90459de0fb312b297b27Juan Cespedes#include "ptrace.h" 30366c2f46d844f040458df9b7e35fc3b8527ed2d3Petr Machata#include "proc.h" 31f728123bd75a65a6a1536e198c3c30719e494e71Juan Cespedes#include "common.h" 325c3fe0697b202cc7d95e90459de0fb312b297b27Juan Cespedes 33f13505251e6402460f6cc7ec84e0d8ca91607b4fJuan Cespedesvoid 34929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machataget_arch_dep(struct process *proc) 35929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machata{ 365c3fe0697b202cc7d95e90459de0fb312b297b27Juan Cespedes proc_archdep *a; 375c3fe0697b202cc7d95e90459de0fb312b297b27Juan Cespedes if (!proc->arch_ptr) 385c3fe0697b202cc7d95e90459de0fb312b297b27Juan Cespedes proc->arch_ptr = (void *)malloc(sizeof(proc_archdep)); 392d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand a = (proc_archdep *) (proc->arch_ptr); 402d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand a->valid = (ptrace(PTRACE_GETREGS, proc->pid, &a->regs, 0) >= 0); 415c3fe0697b202cc7d95e90459de0fb312b297b27Juan Cespedes} 425c3fe0697b202cc7d95e90459de0fb312b297b27Juan Cespedes 435c3fe0697b202cc7d95e90459de0fb312b297b27Juan Cespedes/* Returns syscall number if `pid' stopped because of a syscall. 445c3fe0697b202cc7d95e90459de0fb312b297b27Juan Cespedes * Returns -1 otherwise 455c3fe0697b202cc7d95e90459de0fb312b297b27Juan Cespedes */ 46f13505251e6402460f6cc7ec84e0d8ca91607b4fJuan Cespedesint 47929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machatasyscall_p(struct process *proc, int status, int *sysnum) 48929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machata{ 492d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand if (WIFSTOPPED(status) 502d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand && WSTOPSIG(status) == (SIGTRAP | proc->tracesysgood)) { 515c3fe0697b202cc7d95e90459de0fb312b297b27Juan Cespedes void *ip = get_instruction_pointer(proc); 525c3fe0697b202cc7d95e90459de0fb312b297b27Juan Cespedes unsigned int insn; 532d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand if (ip == (void *)-1) 542d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand return 0; 555c3fe0697b202cc7d95e90459de0fb312b297b27Juan Cespedes insn = ptrace(PTRACE_PEEKTEXT, proc->pid, ip, 0); 565c3fe0697b202cc7d95e90459de0fb312b297b27Juan Cespedes if ((insn & 0xc1f8007f) == 0x81d00010) { 573458456ffbf0b6d85e1818dea7cbeacc8b1d2298Juan Cespedes *sysnum = ((proc_archdep *) proc->arch_ptr)->regs.u_regs[UREG_G0]; 583e94cbf0d388a5b5b49f8dbc60f4b24900de89aeJuan Cespedes if (proc->callstack_depth > 0 && 593e94cbf0d388a5b5b49f8dbc60f4b24900de89aeJuan Cespedes proc->callstack[proc->callstack_depth - 1].is_syscall && 603e94cbf0d388a5b5b49f8dbc60f4b24900de89aeJuan Cespedes proc->callstack[proc->callstack_depth - 1].c_un.syscall == *sysnum) { 615c3fe0697b202cc7d95e90459de0fb312b297b27Juan Cespedes return 2; 622d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand } else if (*sysnum >= 0) { 635c3fe0697b202cc7d95e90459de0fb312b297b27Juan Cespedes return 1; 645c3fe0697b202cc7d95e90459de0fb312b297b27Juan Cespedes } 655c3fe0697b202cc7d95e90459de0fb312b297b27Juan Cespedes } 665c3fe0697b202cc7d95e90459de0fb312b297b27Juan Cespedes } 675c3fe0697b202cc7d95e90459de0fb312b297b27Juan Cespedes return 0; 685c3fe0697b202cc7d95e90459de0fb312b297b27Juan Cespedes} 695c3fe0697b202cc7d95e90459de0fb312b297b27Juan Cespedes 70f13505251e6402460f6cc7ec84e0d8ca91607b4fJuan Cespedeslong 71929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machatagimme_arg(enum tof type, struct process *proc, int arg_num, 72929bd57ca202fd2f2e8485ebf65d683e664f67b5Petr Machata struct arg_type_info *info) 73000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata{ 742d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand proc_archdep *a = (proc_archdep *) proc->arch_ptr; 755c3fe0697b202cc7d95e90459de0fb312b297b27Juan Cespedes if (!a->valid) { 765c3fe0697b202cc7d95e90459de0fb312b297b27Juan Cespedes fprintf(stderr, "Could not get child registers\n"); 775c3fe0697b202cc7d95e90459de0fb312b297b27Juan Cespedes exit(1); 785c3fe0697b202cc7d95e90459de0fb312b297b27Juan Cespedes } 792d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand if (arg_num == -1) /* return value */ 803458456ffbf0b6d85e1818dea7cbeacc8b1d2298Juan Cespedes return a->regs.u_regs[UREG_G7]; 815c3fe0697b202cc7d95e90459de0fb312b297b27Juan Cespedes 822d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand if (type == LT_TOF_FUNCTION || type == LT_TOF_SYSCALL || arg_num >= 6) { 835c3fe0697b202cc7d95e90459de0fb312b297b27Juan Cespedes if (arg_num < 6) 843458456ffbf0b6d85e1818dea7cbeacc8b1d2298Juan Cespedes return ((int *)&a->regs.u_regs[UREG_G7])[arg_num]; 852d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand return ptrace(PTRACE_PEEKTEXT, proc->pid, 862d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand proc->stack_pointer + 64 * (arg_num + 1)); 872d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand } else if (type == LT_TOF_FUNCTIONR) 885c3fe0697b202cc7d95e90459de0fb312b297b27Juan Cespedes return a->func_arg[arg_num]; 892d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand else if (type == LT_TOF_SYSCALLR) 905c3fe0697b202cc7d95e90459de0fb312b297b27Juan Cespedes return a->sysc_arg[arg_num]; 915c3fe0697b202cc7d95e90459de0fb312b297b27Juan Cespedes else { 925c3fe0697b202cc7d95e90459de0fb312b297b27Juan Cespedes fprintf(stderr, "gimme_arg called with wrong arguments\n"); 935c3fe0697b202cc7d95e90459de0fb312b297b27Juan Cespedes exit(1); 945c3fe0697b202cc7d95e90459de0fb312b297b27Juan Cespedes } 955c3fe0697b202cc7d95e90459de0fb312b297b27Juan Cespedes return 0; 965c3fe0697b202cc7d95e90459de0fb312b297b27Juan Cespedes} 97