trace.c revision e99af270a60891e68d465c4cd97dbe29cd1a05e4
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 34a8909f71e1421949c960f287217be6c42c286c0fJuan Cespedesget_arch_dep(Process *proc) { 355c3fe0697b202cc7d95e90459de0fb312b297b27Juan Cespedes proc_archdep *a; 365c3fe0697b202cc7d95e90459de0fb312b297b27Juan Cespedes if (!proc->arch_ptr) 375c3fe0697b202cc7d95e90459de0fb312b297b27Juan Cespedes proc->arch_ptr = (void *)malloc(sizeof(proc_archdep)); 382d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand a = (proc_archdep *) (proc->arch_ptr); 392d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand a->valid = (ptrace(PTRACE_GETREGS, proc->pid, &a->regs, 0) >= 0); 405c3fe0697b202cc7d95e90459de0fb312b297b27Juan Cespedes} 415c3fe0697b202cc7d95e90459de0fb312b297b27Juan Cespedes 425c3fe0697b202cc7d95e90459de0fb312b297b27Juan Cespedes/* Returns syscall number if `pid' stopped because of a syscall. 435c3fe0697b202cc7d95e90459de0fb312b297b27Juan Cespedes * Returns -1 otherwise 445c3fe0697b202cc7d95e90459de0fb312b297b27Juan Cespedes */ 45f13505251e6402460f6cc7ec84e0d8ca91607b4fJuan Cespedesint 46a8909f71e1421949c960f287217be6c42c286c0fJuan Cespedessyscall_p(Process *proc, int status, int *sysnum) { 472d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand if (WIFSTOPPED(status) 482d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand && WSTOPSIG(status) == (SIGTRAP | proc->tracesysgood)) { 495c3fe0697b202cc7d95e90459de0fb312b297b27Juan Cespedes void *ip = get_instruction_pointer(proc); 505c3fe0697b202cc7d95e90459de0fb312b297b27Juan Cespedes unsigned int insn; 512d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand if (ip == (void *)-1) 522d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand return 0; 535c3fe0697b202cc7d95e90459de0fb312b297b27Juan Cespedes insn = ptrace(PTRACE_PEEKTEXT, proc->pid, ip, 0); 545c3fe0697b202cc7d95e90459de0fb312b297b27Juan Cespedes if ((insn & 0xc1f8007f) == 0x81d00010) { 553458456ffbf0b6d85e1818dea7cbeacc8b1d2298Juan Cespedes *sysnum = ((proc_archdep *) proc->arch_ptr)->regs.u_regs[UREG_G0]; 563e94cbf0d388a5b5b49f8dbc60f4b24900de89aeJuan Cespedes if (proc->callstack_depth > 0 && 573e94cbf0d388a5b5b49f8dbc60f4b24900de89aeJuan Cespedes proc->callstack[proc->callstack_depth - 1].is_syscall && 583e94cbf0d388a5b5b49f8dbc60f4b24900de89aeJuan Cespedes proc->callstack[proc->callstack_depth - 1].c_un.syscall == *sysnum) { 595c3fe0697b202cc7d95e90459de0fb312b297b27Juan Cespedes return 2; 602d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand } else if (*sysnum >= 0) { 615c3fe0697b202cc7d95e90459de0fb312b297b27Juan Cespedes return 1; 625c3fe0697b202cc7d95e90459de0fb312b297b27Juan Cespedes } 635c3fe0697b202cc7d95e90459de0fb312b297b27Juan Cespedes } 645c3fe0697b202cc7d95e90459de0fb312b297b27Juan Cespedes } 655c3fe0697b202cc7d95e90459de0fb312b297b27Juan Cespedes return 0; 665c3fe0697b202cc7d95e90459de0fb312b297b27Juan Cespedes} 675c3fe0697b202cc7d95e90459de0fb312b297b27Juan Cespedes 68f13505251e6402460f6cc7ec84e0d8ca91607b4fJuan Cespedeslong 69000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machatagimme_arg(enum tof type, Process *proc, int arg_num, struct arg_type_info *info) 70000e31195ad4ad30a0c80c93ab57a424e7d8d918Petr Machata{ 712d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand proc_archdep *a = (proc_archdep *) proc->arch_ptr; 725c3fe0697b202cc7d95e90459de0fb312b297b27Juan Cespedes if (!a->valid) { 735c3fe0697b202cc7d95e90459de0fb312b297b27Juan Cespedes fprintf(stderr, "Could not get child registers\n"); 745c3fe0697b202cc7d95e90459de0fb312b297b27Juan Cespedes exit(1); 755c3fe0697b202cc7d95e90459de0fb312b297b27Juan Cespedes } 762d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand if (arg_num == -1) /* return value */ 773458456ffbf0b6d85e1818dea7cbeacc8b1d2298Juan Cespedes return a->regs.u_regs[UREG_G7]; 785c3fe0697b202cc7d95e90459de0fb312b297b27Juan Cespedes 792d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand if (type == LT_TOF_FUNCTION || type == LT_TOF_SYSCALL || arg_num >= 6) { 805c3fe0697b202cc7d95e90459de0fb312b297b27Juan Cespedes if (arg_num < 6) 813458456ffbf0b6d85e1818dea7cbeacc8b1d2298Juan Cespedes return ((int *)&a->regs.u_regs[UREG_G7])[arg_num]; 822d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand return ptrace(PTRACE_PEEKTEXT, proc->pid, 832d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand proc->stack_pointer + 64 * (arg_num + 1)); 842d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand } else if (type == LT_TOF_FUNCTIONR) 855c3fe0697b202cc7d95e90459de0fb312b297b27Juan Cespedes return a->func_arg[arg_num]; 862d45b1a8e26a36a9f85dc49e721c4390ca93dc40Ian Wienand else if (type == LT_TOF_SYSCALLR) 875c3fe0697b202cc7d95e90459de0fb312b297b27Juan Cespedes return a->sysc_arg[arg_num]; 885c3fe0697b202cc7d95e90459de0fb312b297b27Juan Cespedes else { 895c3fe0697b202cc7d95e90459de0fb312b297b27Juan Cespedes fprintf(stderr, "gimme_arg called with wrong arguments\n"); 905c3fe0697b202cc7d95e90459de0fb312b297b27Juan Cespedes exit(1); 915c3fe0697b202cc7d95e90459de0fb312b297b27Juan Cespedes } 925c3fe0697b202cc7d95e90459de0fb312b297b27Juan Cespedes return 0; 935c3fe0697b202cc7d95e90459de0fb312b297b27Juan Cespedes} 94