Home | History | Annotate | Download | only in x86
      1 /*
      2  * This file is part of ltrace.
      3  * Copyright (C) 2010,2011,2012 Petr Machata, Red Hat Inc.
      4  * Copyright (C) 2004,2008,2009 Juan Cespedes
      5  * Copyright (C) 2006 Ian Wienand
      6  *
      7  * This program is free software; you can redistribute it and/or
      8  * modify it under the terms of the GNU General Public License as
      9  * published by the Free Software Foundation; either version 2 of the
     10  * License, or (at your option) any later version.
     11  *
     12  * This program is distributed in the hope that it will be useful, but
     13  * WITHOUT ANY WARRANTY; without even the implied warranty of
     14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     15  * 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, write to the Free Software
     19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
     20  * 02110-1301 USA
     21  */
     22 
     23 #include "config.h"
     24 
     25 #include <sys/reg.h>
     26 #include <sys/wait.h>
     27 #include <assert.h>
     28 #include <errno.h>
     29 #include <stdlib.h>
     30 
     31 #include "backend.h"
     32 #include "debug.h"
     33 #include "proc.h"
     34 #include "ptrace.h"
     35 #include "type.h"
     36 
     37 #if (!defined(PTRACE_PEEKUSER) && defined(PTRACE_PEEKUSR))
     38 # define PTRACE_PEEKUSER PTRACE_PEEKUSR
     39 #endif
     40 
     41 #if (!defined(PTRACE_POKEUSER) && defined(PTRACE_POKEUSR))
     42 # define PTRACE_POKEUSER PTRACE_POKEUSR
     43 #endif
     44 
     45 #ifdef __x86_64__
     46 # define ORIG_XAX (8 * ORIG_RAX)
     47 #else
     48 # define ORIG_XAX (4 * ORIG_EAX)
     49 #endif
     50 
     51 #ifdef __x86_64__
     52 static const int x86_64 = 1;
     53 #else
     54 static const int x86_64 = 0;
     55 #endif
     56 
     57 void
     58 get_arch_dep(struct process *proc)
     59 {
     60 	/* Unfortunately there are still remnants of mask_32bit uses
     61 	 * around.  */
     62 
     63 	if (proc->e_machine == EM_X86_64) {
     64 		proc->mask_32bit = 0;
     65 		proc->personality = 1;
     66 	} else if (x86_64) { /* x86_64/i386 */
     67 		proc->mask_32bit = 1;
     68 		proc->personality = 0;
     69 	} else {
     70 		proc->mask_32bit = 0;
     71 		proc->personality = 0;
     72 	}
     73 }
     74 
     75 /* Returns 1 if syscall, 2 if sysret, 0 otherwise.
     76  */
     77 int
     78 syscall_p(struct process *proc, int status, int *sysnum)
     79 {
     80 	if (WIFSTOPPED(status)
     81 	    && WSTOPSIG(status) == (SIGTRAP | proc->tracesysgood)) {
     82 		struct callstack_element *elem = NULL;
     83 		if (proc->callstack_depth > 0)
     84 			elem = proc->callstack + proc->callstack_depth - 1;
     85 
     86 		long int ret = ptrace(PTRACE_PEEKUSER, proc->pid, ORIG_XAX, 0);
     87 		if (ret == -1) {
     88 			if (errno)
     89 				return -1;
     90 			/* Otherwise, ORIG_RAX == -1 means that the
     91 			 * system call should not be restarted.  In
     92 			 * that case rely on what we have on
     93 			 * stack.  */
     94 			if (elem != NULL && elem->is_syscall)
     95 				ret = elem->c_un.syscall;
     96 		}
     97 
     98 		*sysnum = ret;
     99 		debug(DEBUG_FUNCTION, "sysnum=%ld %p %d", ret,
    100 		      get_instruction_pointer(proc), errno);
    101 		if (elem != NULL && elem->is_syscall
    102 		    && elem->c_un.syscall == *sysnum)
    103 			return 2;
    104 
    105 		if (*sysnum >= 0)
    106 			return 1;
    107 	}
    108 	return 0;
    109 }
    110 
    111 size_t
    112 arch_type_sizeof(struct process *proc, struct arg_type_info *info)
    113 {
    114 	if (proc == NULL)
    115 		return (size_t)-2;
    116 
    117 	switch (info->type) {
    118 	case ARGTYPE_VOID:
    119 		return 0;
    120 
    121 	case ARGTYPE_CHAR:
    122 		return 1;
    123 
    124 	case ARGTYPE_SHORT:
    125 	case ARGTYPE_USHORT:
    126 		return 2;
    127 
    128 	case ARGTYPE_INT:
    129 	case ARGTYPE_UINT:
    130 		return 4;
    131 
    132 	case ARGTYPE_LONG:
    133 	case ARGTYPE_ULONG:
    134 	case ARGTYPE_POINTER:
    135 		return proc->e_machine == EM_X86_64 ? 8 : 4;
    136 
    137 	case ARGTYPE_FLOAT:
    138 		return 4;
    139 	case ARGTYPE_DOUBLE:
    140 		return 8;
    141 
    142 	case ARGTYPE_ARRAY:
    143 	case ARGTYPE_STRUCT:
    144 		/* Use default value.  */
    145 		return (size_t)-2;
    146 
    147 	default:
    148 		assert(info->type != info->type);
    149 		abort();
    150 	}
    151 }
    152 
    153 size_t
    154 arch_type_alignof(struct process *proc, struct arg_type_info *info)
    155 {
    156 	if (proc == NULL)
    157 		return (size_t)-2;
    158 
    159 	switch (info->type) {
    160 	default:
    161 		assert(info->type != info->type);
    162 		abort();
    163 		break;
    164 
    165 	case ARGTYPE_CHAR:
    166 		return 1;
    167 
    168 	case ARGTYPE_SHORT:
    169 	case ARGTYPE_USHORT:
    170 		return 2;
    171 
    172 	case ARGTYPE_INT:
    173 	case ARGTYPE_UINT:
    174 		return 4;
    175 
    176 	case ARGTYPE_LONG:
    177 	case ARGTYPE_ULONG:
    178 	case ARGTYPE_POINTER:
    179 		return proc->e_machine == EM_X86_64 ? 8 : 4;
    180 
    181 	case ARGTYPE_FLOAT:
    182 		return 4;
    183 	case ARGTYPE_DOUBLE:
    184 		return proc->e_machine == EM_X86_64 ? 8 : 4;
    185 
    186 	case ARGTYPE_ARRAY:
    187 	case ARGTYPE_STRUCT:
    188 		/* Use default value.  */
    189 		return (size_t)-2;
    190 	}
    191 }
    192