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__
52static const int x86_64 = 1;
53#else
54static const int x86_64 = 0;
55#endif
56
57void
58get_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 */
77int
78syscall_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
111size_t
112arch_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
153size_t
154arch_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