trace.c revision f25af517a06521f69fbc53eaf3c245a7a2298c75
1/*
2 * This file is part of ltrace.
3 * Copyright (C) 2012, 2013 Petr Machata, Red Hat Inc.
4 * Copyright (C) 1998,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 <string.h>
26#include <sys/types.h>
27#include <sys/wait.h>
28#include <signal.h>
29#include <sys/ptrace.h>
30#include <asm/ptrace.h>
31
32#include "bits.h"
33#include "common.h"
34#include "proc.h"
35#include "output.h"
36#include "ptrace.h"
37#include "regs.h"
38#include "type.h"
39
40#if (!defined(PTRACE_PEEKUSER) && defined(PTRACE_PEEKUSR))
41# define PTRACE_PEEKUSER PTRACE_PEEKUSR
42#endif
43
44#if (!defined(PTRACE_POKEUSER) && defined(PTRACE_POKEUSR))
45# define PTRACE_POKEUSER PTRACE_POKEUSR
46#endif
47
48void
49get_arch_dep(struct process *proc)
50{
51	proc_archdep *a;
52
53	if (!proc->arch_ptr)
54		proc->arch_ptr = (void *)malloc(sizeof(proc_archdep));
55	a = (proc_archdep *) (proc->arch_ptr);
56	a->valid = (ptrace(PTRACE_GETREGS, proc->pid, 0, &a->regs) >= 0);
57}
58
59/* Returns 0 if not a syscall,
60 *         1 if syscall entry, 2 if syscall exit,
61 *         3 if arch-specific syscall entry, 4 if arch-specific syscall exit,
62 *         -1 on error.
63 */
64int
65syscall_p(struct process *proc, int status, int *sysnum)
66{
67	if (WIFSTOPPED(status)
68	    && WSTOPSIG(status) == (SIGTRAP | proc->tracesysgood)) {
69		uint32_t pc, ip;
70		if (arm_get_register(proc, ARM_REG_PC, &pc) < 0
71		    || arm_get_register(proc, ARM_REG_IP, &ip) < 0)
72			return -1;
73
74		pc = pc - 4;
75
76		/* fetch the SWI instruction */
77		unsigned insn = ptrace(PTRACE_PEEKTEXT, proc->pid,
78				       (void *)pc, 0);
79
80		if (insn == 0xef000000 || insn == 0x0f000000
81		    || (insn & 0xffff0000) == 0xdf000000) {
82			/* EABI syscall */
83			uint32_t r7;
84			if (arm_get_register(proc, ARM_REG_R7, &r7) < 0)
85				return -1;
86			*sysnum = r7;
87		} else if ((insn & 0xfff00000) == 0xef900000) {
88			/* old ABI syscall */
89			*sysnum = insn & 0xfffff;
90		} else {
91			/* TODO: handle swi<cond> variations */
92			/* one possible reason for getting in here is that we
93			 * are coming from a signal handler, so the current
94			 * PC does not point to the instruction just after the
95			 * "swi" one. */
96			output_line(proc, "unexpected instruction 0x%x at %p",
97				    insn, pc);
98			return 0;
99		}
100		if ((*sysnum & 0xf0000) == 0xf0000) {
101			/* arch-specific syscall */
102			*sysnum &= ~0xf0000;
103			return ip ? 4 : 3;
104		}
105		/* ARM syscall convention: on syscall entry, ip is zero;
106		 * on syscall exit, ip is non-zero */
107		return ip ? 2 : 1;
108	}
109	return 0;
110}
111
112static arch_addr_t
113arm_branch_dest(const arch_addr_t pc, const uint32_t insn)
114{
115	/* Bits 0-23 are signed immediate value.  */
116	return pc + ((((insn & 0xffffff) ^ 0x800000) - 0x800000) << 2) + 8;
117}
118
119/* Addresses for calling Thumb functions have the bit 0 set.
120   Here are some macros to test, set, or clear bit 0 of addresses.  */
121/* XXX double cast */
122#define IS_THUMB_ADDR(addr)	((uintptr_t)(addr) & 1)
123#define MAKE_THUMB_ADDR(addr)	((arch_addr_t)((uintptr_t)(addr) | 1))
124#define UNMAKE_THUMB_ADDR(addr) ((arch_addr_t)((uintptr_t)(addr) & ~1))
125
126enum {
127	COND_ALWAYS = 0xe,
128	COND_NV = 0xf,
129	FLAG_C = 0x20000000,
130};
131
132static int
133arm_get_next_pcs(struct process *proc,
134		 const arch_addr_t pc, arch_addr_t next_pcs[2])
135{
136	uint32_t this_instr;
137	uint32_t status;
138	if (proc_read_32(proc, pc, &this_instr) < 0
139	    || arm_get_register(proc, ARM_REG_CPSR, &status) < 0)
140		return -1;
141
142	/* In theory, we sometimes don't even need to add any
143	 * breakpoints at all.  If the conditional bits of the
144	 * instruction indicate that it should not be taken, then we
145	 * can just skip it altogether without bothering.  We could
146	 * also emulate the instruction under the breakpoint.
147	 *
148	 * Here, we make it as simple as possible (though We Accept
149	 * Patches).  */
150	int nr = 0;
151
152	/* ARM can branch either relatively by using a branch
153	 * instruction, or absolutely, by doing arbitrary arithmetic
154	 * with PC as the destination.  */
155	const unsigned cond = BITS(this_instr, 28, 31);
156	const unsigned opcode = BITS(this_instr, 24, 27);
157
158	if (cond == COND_NV)
159		switch (opcode) {
160			arch_addr_t addr;
161		case 0xa:
162		case 0xb:
163			/* Branch with Link and change to Thumb.  */
164			/* XXX double cast.  */
165			addr = (arch_addr_t)
166				((uint32_t)arm_branch_dest(pc, this_instr)
167				 | (((this_instr >> 24) & 0x1) << 1));
168			next_pcs[nr++] = MAKE_THUMB_ADDR(addr);
169			break;
170		}
171	else
172		switch (opcode) {
173			uint32_t operand1, operand2, result = 0;
174		case 0x0:
175		case 0x1:			/* data processing */
176		case 0x2:
177		case 0x3:
178			if (BITS(this_instr, 12, 15) != ARM_REG_PC)
179				break;
180
181			if (BITS(this_instr, 22, 25) == 0
182			    && BITS(this_instr, 4, 7) == 9) {	/* multiply */
183			invalid:
184				fprintf(stderr,
185				"Invalid update to pc in instruction.\n");
186				break;
187			}
188
189			/* BX <reg>, BLX <reg> */
190			if (BITS(this_instr, 4, 27) == 0x12fff1
191			    || BITS(this_instr, 4, 27) == 0x12fff3) {
192				enum arm_register reg = BITS(this_instr, 0, 3);
193				/* XXX double cast: no need to go
194				 * through tmp.  */
195				uint32_t tmp;
196				if (arm_get_register_offpc(proc, reg, &tmp) < 0)
197					return -1;
198				next_pcs[nr++] = (arch_addr_t)tmp;
199				return 0;
200			}
201
202			/* Multiply into PC.  */
203			if (arm_get_register_offpc
204			    (proc, BITS(this_instr, 16, 19), &operand1) < 0)
205				return -1;
206
207			int c = (status & FLAG_C) ? 1 : 0;
208			if (BIT(this_instr, 25)) {
209				uint32_t immval = BITS(this_instr, 0, 7);
210				uint32_t rotate = 2 * BITS(this_instr, 8, 11);
211				operand2 = (((immval >> rotate)
212					     | (immval << (32 - rotate)))
213					    & 0xffffffff);
214			} else {
215				/* operand 2 is a shifted register.  */
216				if (arm_get_shifted_register
217				    (proc, this_instr, c, pc, &operand2) < 0)
218					return -1;
219			}
220
221			switch (BITS(this_instr, 21, 24)) {
222			case 0x0:	/*and */
223				result = operand1 & operand2;
224				break;
225
226			case 0x1:	/*eor */
227				result = operand1 ^ operand2;
228				break;
229
230			case 0x2:	/*sub */
231				result = operand1 - operand2;
232				break;
233
234			case 0x3:	/*rsb */
235				result = operand2 - operand1;
236				break;
237
238			case 0x4:	/*add */
239				result = operand1 + operand2;
240				break;
241
242			case 0x5:	/*adc */
243				result = operand1 + operand2 + c;
244				break;
245
246			case 0x6:	/*sbc */
247				result = operand1 - operand2 + c;
248				break;
249
250			case 0x7:	/*rsc */
251				result = operand2 - operand1 + c;
252				break;
253
254			case 0x8:
255			case 0x9:
256			case 0xa:
257			case 0xb:	/* tst, teq, cmp, cmn */
258				/* Only take the default branch.  */
259				result = 0;
260				break;
261
262			case 0xc:	/*orr */
263				result = operand1 | operand2;
264				break;
265
266			case 0xd:	/*mov */
267				/* Always step into a function.  */
268				result = operand2;
269				break;
270
271			case 0xe:	/*bic */
272				result = operand1 & ~operand2;
273				break;
274
275			case 0xf:	/*mvn */
276				result = ~operand2;
277				break;
278			}
279
280			/* XXX double cast */
281			next_pcs[nr++] = (arch_addr_t)result;
282			break;
283
284		case 0x4:
285		case 0x5:		/* data transfer */
286		case 0x6:
287		case 0x7:
288			/* Ignore if insn isn't load or Rn not PC.  */
289			if (!BIT(this_instr, 20)
290			    || BITS(this_instr, 12, 15) != ARM_REG_PC)
291				break;
292
293			if (BIT(this_instr, 22))
294				goto invalid;
295
296			/* byte write to PC */
297			uint32_t base;
298			if (arm_get_register_offpc
299			    (proc, BITS(this_instr, 16, 19), &base) < 0)
300				return -1;
301
302			if (BIT(this_instr, 24)) {
303				/* pre-indexed */
304				int c = (status & FLAG_C) ? 1 : 0;
305				uint32_t offset;
306				if (BIT(this_instr, 25)) {
307					if (arm_get_shifted_register
308					    (proc, this_instr, c,
309					     pc, &offset) < 0)
310						return -1;
311				} else {
312					offset = BITS(this_instr, 0, 11);
313				}
314
315				if (BIT(this_instr, 23))
316					base += offset;
317				else
318					base -= offset;
319			}
320
321			/* XXX two double casts.  */
322			uint32_t next;
323			if (proc_read_32(proc, (arch_addr_t)base, &next) < 0)
324				return -1;
325			next_pcs[nr++] = (arch_addr_t)next;
326			break;
327
328		case 0x8:
329		case 0x9:		/* block transfer */
330			if (!BIT(this_instr, 20))
331				break;
332			/* LDM */
333			if (BIT(this_instr, 15)) {
334				/* Loading pc.  */
335				int offset = 0;
336				enum arm_register rn = BITS(this_instr, 16, 19);
337				uint32_t rn_val;
338				if (arm_get_register(proc, rn, &rn_val) < 0)
339					return -1;
340
341				int pre = BIT(this_instr, 24);
342				if (BIT(this_instr, 23)) {
343					/* Bit U = up.  */
344					unsigned reglist
345						= BITS(this_instr, 0, 14);
346					offset = bitcount(reglist) * 4;
347					if (pre)
348						offset += 4;
349				} else if (pre) {
350					offset = -4;
351				}
352
353				/* XXX double cast.  */
354				arch_addr_t addr
355					= (arch_addr_t)(rn_val + offset);
356				uint32_t next;
357				if (proc_read_32(proc, addr, &next) < 0)
358					return -1;
359				next_pcs[nr++] = (arch_addr_t)next;
360			}
361			break;
362
363		case 0xb:		/* branch & link */
364		case 0xa:		/* branch */
365			next_pcs[nr++] = arm_branch_dest(pc, this_instr);
366			break;
367
368		case 0xc:
369		case 0xd:
370		case 0xe:		/* coproc ops */
371		case 0xf:		/* SWI */
372			break;
373		}
374
375	/* Otherwise take the next instruction.  */
376	if (cond != COND_ALWAYS || nr == 0)
377		next_pcs[nr++] = pc + 4;
378	return 0;
379}
380
381/* Return the size in bytes of the complete Thumb instruction whose
382 * first halfword is INST1.  */
383
384static int
385thumb_insn_size (unsigned short inst1)
386{
387  if ((inst1 & 0xe000) == 0xe000 && (inst1 & 0x1800) != 0)
388	  return 4;
389  else
390	  return 2;
391}
392
393static int
394thumb_get_next_pcs(struct process *proc,
395		   const arch_addr_t pc, arch_addr_t next_pcs[2])
396{
397	uint16_t inst1;
398	uint32_t status;
399	if (proc_read_16(proc, pc, &inst1) < 0
400	    || arm_get_register(proc, ARM_REG_CPSR, &status) < 0)
401		return -1;
402
403	int nr = 0;
404
405	/* We currently ignore Thumb-2 conditional execution support
406	 * (the IT instruction).  No branches are allowed in IT block,
407	 * and it's not legal to jump in the middle of it, so unless
408	 * we need to singlestep through large swaths of code, which
409	 * we currently don't, we can ignore them.  */
410
411	if ((inst1 & 0xff00) == 0xbd00)	{ /* pop {rlist, pc} */
412		/* Fetch the saved PC from the stack.  It's stored
413		 * above all of the other registers.  */
414		const unsigned offset = bitcount(BITS(inst1, 0, 7)) * 4;
415		uint32_t sp;
416		uint32_t next;
417		/* XXX two double casts */
418		if (arm_get_register(proc, ARM_REG_SP, &sp) < 0
419		    || proc_read_32(proc, (arch_addr_t)(sp + offset),
420				    &next) < 0)
421			return -1;
422		next_pcs[nr++] = (arch_addr_t)next;
423	} else if ((inst1 & 0xf000) == 0xd000) { /* conditional branch */
424		const unsigned long cond = BITS(inst1, 8, 11);
425		if (cond != 0x0f) { /* SWI */
426			next_pcs[nr++] = pc + (SBITS(inst1, 0, 7) << 1);
427			if (cond == COND_ALWAYS)
428				return 0;
429		}
430	} else if ((inst1 & 0xf800) == 0xe000) { /* unconditional branch */
431		next_pcs[nr++] = pc + (SBITS(inst1, 0, 10) << 1);
432	} else if (thumb_insn_size(inst1) == 4) { /* 32-bit instruction */
433		unsigned short inst2;
434		if (proc_read_16(proc, pc + 2, &inst2) < 0)
435			return -1;
436
437		if ((inst1 & 0xf800) == 0xf000 && (inst2 & 0x8000) == 0x8000) {
438			/* Branches and miscellaneous control instructions.  */
439
440			if ((inst2 & 0x1000) != 0
441			    || (inst2 & 0xd001) == 0xc000) {
442				/* B, BL, BLX.  */
443
444				const int imm1 = SBITS(inst1, 0, 10);
445				const unsigned imm2 = BITS(inst2, 0, 10);
446				const unsigned j1 = BIT(inst2, 13);
447				const unsigned j2 = BIT(inst2, 11);
448
449				int32_t offset
450					= ((imm1 << 12) + (imm2 << 1));
451				offset ^= ((!j2) << 22) | ((!j1) << 23);
452
453				/* XXX double cast */
454				uint32_t next = (uint32_t)(pc + offset);
455				/* For BLX make sure to clear the low bits.  */
456				if (BIT(inst2, 12) == 0)
457					next = next & 0xfffffffc;
458				/* XXX double cast */
459				next_pcs[nr++] = (arch_addr_t)next;
460				return 0;
461			} else if (inst1 == 0xf3de
462				   && (inst2 & 0xff00) == 0x3f00) {
463				/* SUBS PC, LR, #imm8.  */
464				uint32_t next;
465				if (arm_get_register(proc, ARM_REG_LR,
466						     &next) < 0)
467					return -1;
468				next -= inst2 & 0x00ff;
469				/* XXX double cast */
470				next_pcs[nr++] = (arch_addr_t)next;
471				return 0;
472			} else if ((inst2 & 0xd000) == 0x8000
473				   && (inst1 & 0x0380) != 0x0380) {
474				/* Conditional branch.  */
475				const int sign = SBITS(inst1, 10, 10);
476				const unsigned imm1 = BITS(inst1, 0, 5);
477				const unsigned imm2 = BITS(inst2, 0, 10);
478				const unsigned j1 = BIT(inst2, 13);
479				const unsigned j2 = BIT(inst2, 11);
480
481				int32_t offset = (sign << 20)
482					+ (j2 << 19) + (j1 << 18);
483				offset += (imm1 << 12) + (imm2 << 1);
484				next_pcs[nr++] = pc + offset;
485				if (BITS(inst1, 6, 9) == COND_ALWAYS)
486					return 0;
487			}
488		} else if ((inst1 & 0xfe50) == 0xe810) {
489			int load_pc = 1;
490			int offset;
491			const enum arm_register rn = BITS(inst1, 0, 3);
492
493			if (BIT(inst1, 7) && !BIT(inst1, 8)) {
494				/* LDMIA or POP */
495				if (!BIT(inst2, 15))
496					load_pc = 0;
497				offset = bitcount(inst2) * 4 - 4;
498			} else if (!BIT(inst1, 7) && BIT(inst1, 8)) {
499				/* LDMDB */
500				if (!BIT(inst2, 15))
501					load_pc = 0;
502				offset = -4;
503			} else if (BIT(inst1, 7) && BIT(inst1, 8)) {
504				/* RFEIA */
505				offset = 0;
506			} else if (!BIT(inst1, 7) && !BIT(inst1, 8)) {
507				/* RFEDB */
508				offset = -8;
509			} else {
510				load_pc = 0;
511			}
512
513			if (load_pc) {
514				uint32_t addr;
515				if (arm_get_register(proc, rn, &addr) < 0)
516					return -1;
517				arch_addr_t a = (arch_addr_t)(addr + offset);
518				uint32_t next;
519				if (proc_read_32(proc, a, &next) < 0)
520					return -1;
521				/* XXX double cast */
522				next_pcs[nr++] = (arch_addr_t)next;
523			}
524		} else if ((inst1 & 0xffef) == 0xea4f
525			   && (inst2 & 0xfff0) == 0x0f00) {
526			/* MOV PC or MOVS PC.  */
527			const enum arm_register rn = BITS(inst2, 0, 3);
528			uint32_t next;
529			if (arm_get_register(proc, rn, &next) < 0)
530				return -1;
531			/* XXX double cast */
532			next_pcs[nr++] = (arch_addr_t)next;
533		} else if ((inst1 & 0xff70) == 0xf850
534			   && (inst2 & 0xf000) == 0xf000) {
535			/* LDR PC.  */
536			const enum arm_register rn = BITS(inst1, 0, 3);
537			uint32_t base;
538			if (arm_get_register(proc, rn, &base) < 0)
539				return -1;
540
541			int load_pc = 1;
542			if (rn == ARM_REG_PC) {
543				base = (base + 4) & ~(uint32_t)0x3;
544				if (BIT(inst1, 7))
545					base += BITS(inst2, 0, 11);
546				else
547					base -= BITS(inst2, 0, 11);
548			} else if (BIT(inst1, 7)) {
549				base += BITS(inst2, 0, 11);
550			} else if (BIT(inst2, 11)) {
551				if (BIT(inst2, 10)) {
552					if (BIT(inst2, 9))
553						base += BITS(inst2, 0, 7);
554					else
555						base -= BITS(inst2, 0, 7);
556				}
557			} else if ((inst2 & 0x0fc0) == 0x0000) {
558				const int shift = BITS(inst2, 4, 5);
559				const enum arm_register rm = BITS(inst2, 0, 3);
560				uint32_t v;
561				if (arm_get_register(proc, rm, &v) < 0)
562					return -1;
563				base += v << shift;
564			} else {
565				/* Reserved.  */
566				load_pc = 0;
567			}
568
569			if (load_pc) {
570				/* xxx double casts */
571				uint32_t next;
572				if (proc_read_32(proc,
573						 (arch_addr_t)base, &next) < 0)
574					return -1;
575				next_pcs[nr++] = (arch_addr_t)next;
576			}
577		} else if ((inst1 & 0xfff0) == 0xe8d0
578			   && (inst2 & 0xfff0) == 0xf000) {
579			/* TBB.  */
580			const enum arm_register tbl_reg = BITS(inst1, 0, 3);
581			const enum arm_register off_reg = BITS(inst2, 0, 3);
582
583			uint32_t table;
584			if (tbl_reg == ARM_REG_PC)
585				/* Regcache copy of PC isn't right yet.  */
586				/* XXX double cast */
587				table = (uint32_t)pc + 4;
588			else if (arm_get_register(proc, tbl_reg, &table) < 0)
589				return -1;
590
591			uint32_t offset;
592			if (arm_get_register(proc, off_reg, &offset) < 0)
593				return -1;
594
595			table += offset;
596			uint8_t length;
597			/* XXX double cast */
598			if (proc_read_8(proc, (arch_addr_t)table, &length) < 0)
599				return -1;
600
601			next_pcs[nr++] = pc + 2 * length;
602
603		} else if ((inst1 & 0xfff0) == 0xe8d0
604			   && (inst2 & 0xfff0) == 0xf010) {
605			/* TBH.  */
606			const enum arm_register tbl_reg = BITS(inst1, 0, 3);
607			const enum arm_register off_reg = BITS(inst2, 0, 3);
608
609			uint32_t table;
610			if (tbl_reg == ARM_REG_PC)
611				/* Regcache copy of PC isn't right yet.  */
612				/* XXX double cast */
613				table = (uint32_t)pc + 4;
614			else if (arm_get_register(proc, tbl_reg, &table) < 0)
615				return -1;
616
617			uint32_t offset;
618			if (arm_get_register(proc, off_reg, &offset) < 0)
619				return -1;
620
621			table += 2 * offset;
622			uint16_t length;
623			/* XXX double cast */
624			if (proc_read_16(proc, (arch_addr_t)table, &length) < 0)
625				return -1;
626
627			next_pcs[nr++] = pc + 2 * length;
628		}
629	}
630
631
632	/* Otherwise take the next instruction.  */
633	if (nr == 0)
634		next_pcs[nr++] = pc + thumb_insn_size(inst1);
635	return 0;
636}
637
638enum sw_singlestep_status
639arch_sw_singlestep(struct process *proc, struct breakpoint *sbp,
640		   int (*add_cb)(arch_addr_t, struct sw_singlestep_data *),
641		   struct sw_singlestep_data *add_cb_data)
642{
643	const arch_addr_t pc = get_instruction_pointer(proc);
644
645	uint32_t cpsr;
646	if (arm_get_register(proc, ARM_REG_CPSR, &cpsr) < 0)
647		return SWS_FAIL;
648
649	const unsigned thumb_p = BIT(cpsr, 5);
650	arch_addr_t next_pcs[2] = {};
651	if ((thumb_p ? &thumb_get_next_pcs
652	     : &arm_get_next_pcs)(proc, pc, next_pcs) < 0)
653		return SWS_FAIL;
654
655	int i;
656	for (i = 0; i < 2; ++i) {
657		/* XXX double cast.  */
658		arch_addr_t target
659			= (arch_addr_t)(((uintptr_t)next_pcs[i]) | thumb_p);
660		if (next_pcs[i] != 0 && add_cb(target, add_cb_data) < 0)
661			return SWS_FAIL;
662	}
663
664	debug(1, "PTRACE_CONT");
665	ptrace(PTRACE_CONT, proc->pid, 0, 0);
666	return SWS_OK;
667}
668
669size_t
670arch_type_sizeof(struct process *proc, struct arg_type_info *info)
671{
672	if (proc == NULL)
673		return (size_t)-2;
674
675	switch (info->type) {
676	case ARGTYPE_VOID:
677		return 0;
678
679	case ARGTYPE_CHAR:
680		return 1;
681
682	case ARGTYPE_SHORT:
683	case ARGTYPE_USHORT:
684		return 2;
685
686	case ARGTYPE_INT:
687	case ARGTYPE_UINT:
688	case ARGTYPE_LONG:
689	case ARGTYPE_ULONG:
690	case ARGTYPE_POINTER:
691		return 4;
692
693	case ARGTYPE_FLOAT:
694		return 4;
695	case ARGTYPE_DOUBLE:
696		return 8;
697
698	case ARGTYPE_ARRAY:
699	case ARGTYPE_STRUCT:
700		/* Use default value.  */
701		return (size_t)-2;
702
703	default:
704		assert(info->type != info->type);
705		abort();
706	}
707}
708
709size_t
710arch_type_alignof(struct process *proc, struct arg_type_info *info)
711{
712	return arch_type_sizeof(proc, info);
713}
714