1From 5f6dfafb80bdc2566fe91d5fde96769175fabf35 Mon Sep 17 00:00:00 2001
2From: Faraz Shahbazker <faraz.shahbazker@imgtec.com>
3Date: Sat, 1 Jul 2017 10:56:59 -0700
4Subject: [PATCH] Add support for mips64 n32/n64
5
6Signed-off-by: Khem Raj <raj.khem@gmail.com>
7---
8Upstream-Status: Pending
9Source: http://lists.alioth.debian.org/pipermail/ltrace-devel/2015-May/001327.html
10
11 backend.h                            |   8 +
12 ltrace-elf.c                         |  12 ++
13 proc.h                               |   1 +
14 sysdeps/linux-gnu/mips/Makefile.am   |   1 +
15 sysdeps/linux-gnu/mips/abi.c         |  64 +++++++
16 sysdeps/linux-gnu/mips/arch.h        |  24 ++-
17 sysdeps/linux-gnu/mips/plt.c         |  68 ++++++--
18 sysdeps/linux-gnu/mips/signalent1.h  |  52 ++++++
19 sysdeps/linux-gnu/mips/syscallent1.h | 328 +++++++++++++++++++++++++++++++++++
20 sysdeps/linux-gnu/mips/trace.c       | 241 ++++++++++++++++++-------
21 sysdeps/linux-gnu/mksyscallent_mips  |   9 +-
22 11 files changed, 728 insertions(+), 80 deletions(-)
23 create mode 100644 sysdeps/linux-gnu/mips/abi.c
24 create mode 100644 sysdeps/linux-gnu/mips/signalent1.h
25 create mode 100644 sysdeps/linux-gnu/mips/syscallent1.h
26
27diff --git a/backend.h b/backend.h
28index e25daa0..0d6926a 100644
29--- a/backend.h
30+++ b/backend.h
31@@ -314,6 +314,14 @@ int arch_process_exec(struct process *proc);
32 int arch_get_sym_info(struct ltelf *lte, const char *filename, size_t sym_index,
33 		      GElf_Rela *rela, GElf_Sym *sym);
34
35+/* The following callback has to be implemented in backend if arch.h
36+ * defines ARCH_HAVE_GET_ABI
37+ *
38+ * This is called from read_module just once, when reading the main module.
39+ * The value returned is an architecture specific ID for the current ABI
40+ * to be used later for ABI-specific operations. */
41+char arch_get_abi(GElf_Ehdr ehdr);
42+
43 enum plt_status {
44 	PLT_FAIL,
45 	PLT_OK,
46diff --git a/ltrace-elf.c b/ltrace-elf.c
47index f439cb0..a85edca 100644
48--- a/ltrace-elf.c
49+++ b/ltrace-elf.c
50@@ -1131,6 +1131,14 @@ populate_symtab(struct process *proc, const char *filename,
51 				    only_exported_names);
52 }
53
54+#ifndef ARCH_HAVE_GET_ABI
55+char
56+arch_get_abi(GElf_Ehdr ehdr)
57+{
58+       return 0;
59+}
60+#endif
61+
62 static int
63 read_module(struct library *lib, struct process *proc,
64 	    const char *filename, GElf_Addr bias, int main)
65@@ -1151,6 +1159,10 @@ read_module(struct library *lib, struct process *proc,
66 	 * with 32-bit ltrace.  It is desirable to preserve this.  */
67 	proc->e_machine = lte.ehdr.e_machine;
68 	proc->e_class = lte.ehdr.e_ident[EI_CLASS];
69+	/* Another candidate for the ABI module. We probably
70+	 * want to do all of the e_* stuff only once, for main */
71+	if (main)
72+		proc->e_abi = arch_get_abi(lte.ehdr);
73 	get_arch_dep(proc);
74
75 	/* Find out the base address.  For PIE main binaries we look
76diff --git a/proc.h b/proc.h
77index a611456..00094e1 100644
78--- a/proc.h
79+++ b/proc.h
80@@ -117,6 +117,7 @@ struct process {
81 	 * nauseam.  */
82 	short e_machine;
83 	char e_class;
84+	char e_abi;
85
86 #if defined(HAVE_LIBDW)
87 	/* Unwind info for leader, NULL for non-leader procs. */
88diff --git a/sysdeps/linux-gnu/mips/Makefile.am b/sysdeps/linux-gnu/mips/Makefile.am
89index 1fd8c2a..571ee0d 100644
90--- a/sysdeps/linux-gnu/mips/Makefile.am
91+++ b/sysdeps/linux-gnu/mips/Makefile.am
92@@ -20,6 +20,7 @@ noinst_LTLIBRARIES = \
93 	../libcpu.la
94
95 ___libcpu_la_SOURCES = \
96+	abi.c \
97 	plt.c \
98 	regs.c \
99 	trace.c
100diff --git a/sysdeps/linux-gnu/mips/abi.c b/sysdeps/linux-gnu/mips/abi.c
101new file mode 100644
102index 0000000..64e3c10
103--- /dev/null
104+++ b/sysdeps/linux-gnu/mips/abi.c
105@@ -0,0 +1,64 @@
106+/*
107+ * This file is part of ltrace.
108+ * Copyright (C) 2015 Imagination Technologies Limited
109+ *
110+ * This program is free software; you can redistribute it and/or
111+ * modify it under the terms of the GNU General Public License as
112+ * published by the Free Software Foundation; either version 2 of the
113+ * License, or (at your option) any later version.
114+ *
115+ * This program is distributed in the hope that it will be useful, but
116+ * WITHOUT ANY WARRANTY; without even the implied warranty of
117+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
118+ * General Public License for more details.
119+ *
120+ * You should have received a copy of the GNU General Public License
121+ * along with this program; if not, write to the Free Software
122+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
123+ * 02110-1301 USA
124+ */
125+
126+#include <stdio.h>
127+#include <gelf.h>
128+#include "arch.h"
129+
130+/*
131+ *  There is no bit in the header-flags to mark N64 ABI, it must be
132+ *  determined by exclusion of other ABIs. The following values are
133+ *  from elfcpp/mips.h in binutils sources
134+ */
135+enum
136+{
137+	E_MIPS_ABI_MASK = 0x0000F000,
138+	E_MIPS_ABI_N32 	= 0x00000020,
139+	E_MIPS_ABI_O32 	= 0x00001000,
140+	E_MIPS_ABI_O64 	= 0x00002000,
141+	E_MIPS_ABI_EABI32 = 0x00003000,
142+	E_MIPS_ABI_EABI64 = 0x00004000,
143+};
144+
145+char
146+arch_get_abi(GElf_Ehdr ehdr)
147+{
148+	enum mips_abi_type abi;
149+	switch (ehdr.e_flags & E_MIPS_ABI_MASK) {
150+	case E_MIPS_ABI_O32:
151+		abi = ABI_O32; break;
152+	case E_MIPS_ABI_O64:
153+		abi = ABI_O64; break;
154+	case E_MIPS_ABI_EABI32:
155+	case E_MIPS_ABI_EABI64:
156+		fprintf(stderr, "%s: MIPS EABI is not supported\n", __func__);
157+		abi = -1;
158+		break;
159+	default:
160+		if (ehdr.e_flags & E_MIPS_ABI_N32)
161+			abi = ABI_N32;
162+		else
163+			abi = ABI_N64;
164+	}
165+
166+	return abi;
167+}
168+
169+/**@}*/
170diff --git a/sysdeps/linux-gnu/mips/arch.h b/sysdeps/linux-gnu/mips/arch.h
171index 16273d2..8b75df2 100644
172--- a/sysdeps/linux-gnu/mips/arch.h
173+++ b/sysdeps/linux-gnu/mips/arch.h
174@@ -1,5 +1,6 @@
175 /*
176  * This file is part of ltrace.
177+ * Copyright (C) 2015 Imagination Technologies Limited
178  * Copyright (C) 2013,2014 Petr Machata, Red Hat Inc.
179  * Copyright (C) 2006 Eric Vaitl
180  *
181@@ -38,8 +39,12 @@
182 #define BREAKPOINT_LENGTH 4
183 #define DECR_PC_AFTER_BREAK 0
184
185-#define LT_ELFCLASS	ELFCLASS32
186+#ifdef __LP64__
187+#define LT_ELFCLASS	ELFCLASS64
188 #define LT_ELF_MACHINE	EM_MIPS
189+#endif /* __LP64__ */
190+#define LT_ELFCLASS2	ELFCLASS32
191+#define LT_ELF_MACHINE2 EM_MIPS
192
193 #define ARCH_HAVE_LTELF_DATA
194 struct arch_ltelf_data {
195@@ -53,8 +58,14 @@ struct arch_ltelf_data {
196 #define ARCH_HAVE_ADD_PLT_ENTRY
197 #define ARCH_HAVE_SW_SINGLESTEP
198 #define ARCH_HAVE_SYMBOL_RET
199-
200+#define ARCH_HAVE_GET_ABI
201 #define ARCH_HAVE_LIBRARY_SYMBOL_DATA
202+
203+#ifdef __LP64__
204+#define ARCH_HAVE_SIZEOF
205+#define ARCH_HAVE_ALIGNOF
206+#endif /* __LP64__ */
207+
208 enum mips_plt_type
209 {
210 	/* A symbol has associated PLT entry.  */
211@@ -73,7 +84,14 @@ enum mips_plt_type
212 	MIPS_PLT_NEED_UNRESOLVE,
213 };
214
215-struct mips_unresolve_data;
216+enum mips_abi_type
217+{
218+	ABI_O32,
219+	ABI_N32,
220+	ABI_N64,
221+	ABI_O64,
222+};
223+
224 struct arch_library_symbol_data {
225 	enum mips_plt_type type;
226 	union {
227diff --git a/sysdeps/linux-gnu/mips/plt.c b/sysdeps/linux-gnu/mips/plt.c
228index f3c12da..2d85ad9 100644
229--- a/sysdeps/linux-gnu/mips/plt.c
230+++ b/sysdeps/linux-gnu/mips/plt.c
231@@ -1,5 +1,6 @@
232 /*
233  * This file is part of ltrace.
234+ * Copyright (C) 2015 Imagination Technologies Limited
235  * Copyright (C) 2012,2013,2014 Petr Machata, Red Hat Inc.
236  * Copyright (C) 2012 Edgar E. Iglesias, Axis Communications
237  * Copyright (C) 2008,2009 Juan Cespedes
238@@ -182,6 +183,11 @@ arch_find_dl_debug(struct process *proc, arch_addr_t dyn_addr,
239 {
240 	arch_addr_t rld_addr;
241 	int r;
242+#ifdef __LP64__
243+	size_t addrsize = proc->mask_32bit ? 4 : (sizeof *ret);
244+#else /* !__LP64__ */
245+	size_t addrsize = sizeof *ret;
246+#endif /* !__LP64__ */
247
248 	/* MIPS puts the address of the r_debug structure into the
249 	 * DT_MIPS_RLD_MAP entry instead of into the DT_DEBUG entry.  */
250@@ -189,7 +195,7 @@ arch_find_dl_debug(struct process *proc, arch_addr_t dyn_addr,
251 					 DT_MIPS_RLD_MAP, &rld_addr);
252 	if (r == 0) {
253 		if (umovebytes(proc, rld_addr,
254-			       ret, sizeof *ret) != sizeof *ret) {
255+			       ret, addrsize) != addrsize) {
256 			r = -1;
257 		}
258 	}
259@@ -295,14 +301,25 @@ arch_elf_init(struct ltelf *lte, struct library *lib)
260
261 	for (j = 0; j < data->d_size / 16; ++j) {
262 		uint32_t insn;
263+		int got_size = 4;
264+		uint32_t load_inst = 0x24180000U; /* addui t8,0,xx  */
265+
266+#ifdef __LP64__
267+		if (arch_get_abi(lte->ehdr) == ABI_N64
268+		    || arch_get_abi(lte->ehdr) == ABI_O64) {
269+			got_size = 8;
270+			load_inst = 0x64180000U; /* daddui t8,0,xx  */
271+		}
272+#endif /* __LP64__ */
273+
274 		if (elf_read_u32(data, j * 16 + 12, &insn) < 0)
275 			goto fail_stubs;
276
277 		if (insn == 0)
278 			continue;
279
280-		/* 0x2418XXXX encodes lbu 0,t8,XXXX or li t8,XXXX.  */
281-		if ((insn & 0xffff0000U) != 0x24180000U)
282+		/* 0x[62]418XXXX encodes [d]addiu t8, 0, XXXX.  */
283+		if ((insn & 0xffff0000U) != load_inst)
284 			goto fail_stubs;
285
286 		unsigned idx = insn & 0xffff;
287@@ -323,8 +340,8 @@ arch_elf_init(struct ltelf *lte, struct library *lib)
288 			+ lte->arch.mips_local_gotno;
289 		/* XXX Double cast.  */
290 		arch_addr_t got_entry_addr
291-			= (arch_addr_t) (uintptr_t) lte->arch.pltgot_addr
292-			+ got_idx * 4;
293+			= (arch_addr_t) (uintptr_t) (lte->arch.pltgot_addr
294+						     + got_idx * got_size);
295
296 		GElf_Rela rela = {
297 			/* XXX double cast.  */
298@@ -336,7 +353,7 @@ arch_elf_init(struct ltelf *lte, struct library *lib)
299 		if (VECT_PUSHBACK(&lte->plt_relocs, &rela) < 0)
300 			goto fail_stubs;
301
302-		fprintf(stderr,
303+		debug(2,
304 			"added stub entry for symbol %u at %#lx, GOT @%p\n",
305 			idx, (unsigned long) rela.r_addend, got_entry_addr);
306 	}
307@@ -362,8 +379,17 @@ read_got_entry(struct process *proc, GElf_Addr addr, GElf_Addr *valp)
308 {
309 	/* XXX double cast.  */
310 	arch_addr_t a = (arch_addr_t) (uintptr_t) addr;
311-	uint32_t l;
312-	if (proc_read_32(proc, a, &l) < 0) {
313+	uint64_t l = 0;
314+	int result;
315+
316+#ifdef __LP64__
317+	if (!proc->mask_32bit)
318+		result = proc_read_64(proc, a, &l);
319+	else
320+#endif /* __LP64__ */
321+		result = proc_read_32(proc, a, (uint32_t *) &l);
322+
323+	if (result < 0) {
324 		fprintf(stderr, "ptrace read got entry @%#" PRIx64 ": %s\n",
325 			addr, strerror(errno));
326 		return -1;
327@@ -426,13 +452,13 @@ arch_elf_add_plt_entry(struct process *proc, struct ltelf *lte,
328 	GElf_Addr stub_addr = rela->r_addend + lte->bias;
329
330 	debug(2, "PLT-less arch_elf_add_plt_entry %s = %#llx\n",
331-	      a_name, stub_addr);
332+	      a_name, (unsigned long long) stub_addr);
333
334 	struct library_symbol *libsym = NULL;
335 	if (default_elf_add_plt_entry(proc, lte, a_name, rela, ndx,
336 				      &libsym) < 0) {
337-		fprintf(stderr, "%s: failed %s(%#llx): %s\n", __func__,
338-			a_name, stub_addr, strerror(errno));
339+		fprintf(stderr, "%s: failed %s(%#lx): %s\n", __func__,
340+			a_name, (unsigned long) stub_addr, strerror(errno));
341 		goto fail;
342 	}
343
344@@ -503,13 +529,27 @@ jump_to_entry_point(struct process *proc, struct breakpoint *bp)
345 static int
346 unresolve_got_entry(struct process *proc, GElf_Addr addr, GElf_Addr value)
347 {
348-	uint32_t v32 = (uint32_t) value;
349-	uint32_t a32 = (uint32_t) addr;
350-	if (ptrace(PTRACE_POKETEXT, proc->pid, a32, v32) < 0) {
351+	arch_addr_t a = (arch_addr_t) (uintptr_t) addr;
352+#ifdef __LP64__
353+	/* To write 32-bit value in 64-bit mode, we must read-modify-write
354+	   the 64-bit value with only the lower 32 bits modified.  */
355+	if (proc->mask_32bit) {
356+		GElf_Addr orig = ptrace(PTRACE_PEEKTEXT, proc->pid, a, 0);
357+		char *obytes = (char *) &orig;
358+		char *nbytes = (char *) &value;
359+		unsigned i;
360+
361+		for (i = 0; i < 4; i++)
362+			obytes[i] = nbytes[i];
363+		value = orig;
364+	}
365+#endif /* __LP64__ */
366+	if (ptrace(PTRACE_POKETEXT, proc->pid, a, (unsigned long) value) < 0) {
367 		fprintf(stderr, "failed to unresolve GOT entry: %s\n",
368 			strerror(errno));
369 		return -1;
370 	}
371+
372 	return 0;
373 }
374
375diff --git a/sysdeps/linux-gnu/mips/signalent1.h b/sysdeps/linux-gnu/mips/signalent1.h
376new file mode 100644
377index 0000000..9e9d1f7
378--- /dev/null
379+++ b/sysdeps/linux-gnu/mips/signalent1.h
380@@ -0,0 +1,52 @@
381+/*
382+ * This file is part of ltrace.
383+ * Copyright (C) 2015 Imagination Technologies Limited
384+ *
385+ * This program is free software; you can redistribute it and/or
386+ * modify it under the terms of the GNU General Public License as
387+ * published by the Free Software Foundation; either version 2 of the
388+ * License, or (at your option) any later version.
389+ *
390+ * This program is distributed in the hope that it will be useful, but
391+ * WITHOUT ANY WARRANTY; without even the implied warranty of
392+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
393+ * General Public License for more details.
394+ *
395+ * You should have received a copy of the GNU General Public License
396+ * along with this program; if not, write to the Free Software
397+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
398+ * 02110-1301 USA
399+ */
400+
401+	"SIG_0",           /* 0 */
402+	"SIGHUP",          /* 1 */
403+	"SIGINT",          /* 2 */
404+	"SIGQUIT",         /* 3 */
405+	"SIGILL",          /* 4 */
406+	"SIGTRAP",         /* 5 */
407+	"SIGIOT",          /* 6 */
408+	"SIGEMT",          /* 7 */
409+	"SIGFPE",          /* 8 */
410+	"SIGKILL",         /* 9 */
411+	"SIGBUS",          /* 10 */
412+	"SIGSEGV",         /* 11 */
413+	"SIGSYS",          /* 12 */
414+	"SIGPIPE",         /* 13 */
415+	"SIGALRM",         /* 14 */
416+	"SIGTERM",         /* 15 */
417+	"SIGUSR1",         /* 16 */
418+	"SIGUSR2",         /* 17 */
419+	"SIGCHLD",         /* 18 */
420+	"SIGPWR",          /* 19 */
421+	"SIGWINCH",        /* 20 */
422+	"SIGURG",          /* 21 */
423+	"SIGIO",           /* 22 */
424+	"SIGSTOP",         /* 23 */
425+	"SIGTSTP",         /* 24 */
426+	"SIGCONT",         /* 25 */
427+	"SIGTTIN",         /* 26 */
428+	"SIGTTOU",         /* 27 */
429+	"SIGVTALRM",       /* 28 */
430+	"SIGPROF",         /* 29 */
431+	"SIGXCPU",         /* 30 */
432+	"SIGXFSZ",         /* 31 */
433diff --git a/sysdeps/linux-gnu/mips/syscallent1.h b/sysdeps/linux-gnu/mips/syscallent1.h
434new file mode 100644
435index 0000000..dfa4954
436--- /dev/null
437+++ b/sysdeps/linux-gnu/mips/syscallent1.h
438@@ -0,0 +1,328 @@
439+/*
440+ * This file is part of ltrace.
441+ * Copyright (C) 2015 Imagination Technologies Limited
442+ *
443+ * This program is free software; you can redistribute it and/or
444+ * modify it under the terms of the GNU General Public License as
445+ * published by the Free Software Foundation; either version 2 of the
446+ * License, or (at your option) any later version.
447+ *
448+ * This program is distributed in the hope that it will be useful, but
449+ * WITHOUT ANY WARRANTY; without even the implied warranty of
450+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
451+ * General Public License for more details.
452+ *
453+ * You should have received a copy of the GNU General Public License
454+ * along with this program; if not, write to the Free Software
455+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
456+ * 02110-1301 USA
457+ */
458+
459+/* MIPS64 */
460+
461+	"read",                            /* 0 */
462+	"write",                           /* 1 */
463+	"open",                            /* 2 */
464+	"close",                           /* 3 */
465+	"stat",                            /* 4 */
466+	"fstat",                           /* 5 */
467+	"lstat",                           /* 6 */
468+	"poll",                            /* 7 */
469+	"lseek",                           /* 8 */
470+	"mmap",                            /* 9 */
471+	"mprotect",                        /* 10 */
472+	"munmap",                          /* 11 */
473+	"brk",                             /* 12 */
474+	"rt_sigaction",                    /* 13 */
475+	"rt_sigprocmask",                  /* 14 */
476+	"ioctl",                           /* 15 */
477+	"pread64",                         /* 16 */
478+	"pwrite64",                        /* 17 */
479+	"readv",                           /* 18 */
480+	"writev",                          /* 19 */
481+	"access",                          /* 20 */
482+	"pipe",                            /* 21 */
483+	"_newselect",                      /* 22 */
484+	"sched_yield",                     /* 23 */
485+	"mremap",                          /* 24 */
486+	"msync",                           /* 25 */
487+	"mincore",                         /* 26 */
488+	"madvise",                         /* 27 */
489+	"shmget",                          /* 28 */
490+	"shmat",                           /* 29 */
491+	"shmctl",                          /* 30 */
492+	"dup",                             /* 31 */
493+	"dup2",                            /* 32 */
494+	"pause",                           /* 33 */
495+	"nanosleep",                       /* 34 */
496+	"getitimer",                       /* 35 */
497+	"setitimer",                       /* 36 */
498+	"alarm",                           /* 37 */
499+	"getpid",                          /* 38 */
500+	"sendfile",                        /* 39 */
501+	"socket",                          /* 40 */
502+	"connect",                         /* 41 */
503+	"accept",                          /* 42 */
504+	"sendto",                          /* 43 */
505+	"recvfrom",                        /* 44 */
506+	"sendmsg",                         /* 45 */
507+	"recvmsg",                         /* 46 */
508+	"shutdown",                        /* 47 */
509+	"bind",                            /* 48 */
510+	"listen",                          /* 49 */
511+	"getsockname",                     /* 50 */
512+	"getpeername",                     /* 51 */
513+	"socketpair",                      /* 52 */
514+	"setsockopt",                      /* 53 */
515+	"getsockopt",                      /* 54 */
516+	"clone",                           /* 55 */
517+	"fork",                            /* 56 */
518+	"execve",                          /* 57 */
519+	"exit",                            /* 58 */
520+	"wait4",                           /* 59 */
521+	"kill",                            /* 60 */
522+	"uname",                           /* 61 */
523+	"semget",                          /* 62 */
524+	"semop",                           /* 63 */
525+	"semctl",                          /* 64 */
526+	"shmdt",                           /* 65 */
527+	"msgget",                          /* 66 */
528+	"msgsnd",                          /* 67 */
529+	"msgrcv",                          /* 68 */
530+	"msgctl",                          /* 69 */
531+	"fcntl",                           /* 70 */
532+	"flock",                           /* 71 */
533+	"fsync",                           /* 72 */
534+	"fdatasync",                       /* 73 */
535+	"truncate",                        /* 74 */
536+	"ftruncate",                       /* 75 */
537+	"getdents",                        /* 76 */
538+	"getcwd",                          /* 77 */
539+	"chdir",                           /* 78 */
540+	"fchdir",                          /* 79 */
541+	"rename",                          /* 80 */
542+	"mkdir",                           /* 81 */
543+	"rmdir",                           /* 82 */
544+	"creat",                           /* 83 */
545+	"link",                            /* 84 */
546+	"unlink",                          /* 85 */
547+	"symlink",                         /* 86 */
548+	"readlink",                        /* 87 */
549+	"chmod",                           /* 88 */
550+	"fchmod",                          /* 89 */
551+	"chown",                           /* 90 */
552+	"fchown",                          /* 91 */
553+	"lchown",                          /* 92 */
554+	"umask",                           /* 93 */
555+	"gettimeofday",                    /* 94 */
556+	"getrlimit",                       /* 95 */
557+	"getrusage",                       /* 96 */
558+	"sysinfo",                         /* 97 */
559+	"times",                           /* 98 */
560+	"ptrace",                          /* 99 */
561+	"getuid",                          /* 100 */
562+	"syslog",                          /* 101 */
563+	"getgid",                          /* 102 */
564+	"setuid",                          /* 103 */
565+	"setgid",                          /* 104 */
566+	"geteuid",                         /* 105 */
567+	"getegid",                         /* 106 */
568+	"setpgid",                         /* 107 */
569+	"getppid",                         /* 108 */
570+	"getpgrp",                         /* 109 */
571+	"setsid",                          /* 110 */
572+	"setreuid",                        /* 111 */
573+	"setregid",                        /* 112 */
574+	"getgroups",                       /* 113 */
575+	"setgroups",                       /* 114 */
576+	"setresuid",                       /* 115 */
577+	"getresuid",                       /* 116 */
578+	"setresgid",                       /* 117 */
579+	"getresgid",                       /* 118 */
580+	"getpgid",                         /* 119 */
581+	"setfsuid",                        /* 120 */
582+	"setfsgid",                        /* 121 */
583+	"getsid",                          /* 122 */
584+	"capget",                          /* 123 */
585+	"capset",                          /* 124 */
586+	"rt_sigpending",                   /* 125 */
587+	"rt_sigtimedwait",                 /* 126 */
588+	"rt_sigqueueinfo",                 /* 127 */
589+	"rt_sigsuspend",                   /* 128 */
590+	"sigaltstack",                     /* 129 */
591+	"utime",                           /* 130 */
592+	"mknod",                           /* 131 */
593+	"personality",                     /* 132 */
594+	"ustat",                           /* 133 */
595+	"statfs",                          /* 134 */
596+	"fstatfs",                         /* 135 */
597+	"sysfs",                           /* 136 */
598+	"getpriority",                     /* 137 */
599+	"setpriority",                     /* 138 */
600+	"sched_setparam",                  /* 139 */
601+	"sched_getparam",                  /* 140 */
602+	"sched_setscheduler",              /* 141 */
603+	"sched_getscheduler",              /* 142 */
604+	"sched_get_priority_max",          /* 143 */
605+	"sched_get_priority_min",          /* 144 */
606+	"sched_rr_get_interval",           /* 145 */
607+	"mlock",                           /* 146 */
608+	"munlock",                         /* 147 */
609+	"mlockall",                        /* 148 */
610+	"munlockall",                      /* 149 */
611+	"vhangup",                         /* 150 */
612+	"pivot_root",                      /* 151 */
613+	"_sysctl",                         /* 152 */
614+	"prctl",                           /* 153 */
615+	"adjtimex",                        /* 154 */
616+	"setrlimit",                       /* 155 */
617+	"chroot",                          /* 156 */
618+	"sync",                            /* 157 */
619+	"acct",                            /* 158 */
620+	"settimeofday",                    /* 159 */
621+	"mount",                           /* 160 */
622+	"umount2",                         /* 161 */
623+	"swapon",                          /* 162 */
624+	"swapoff",                         /* 163 */
625+	"reboot",                          /* 164 */
626+	"sethostname",                     /* 165 */
627+	"setdomainname",                   /* 166 */
628+	"create_module",                   /* 167 */
629+	"init_module",                     /* 168 */
630+	"delete_module",                   /* 169 */
631+	"get_kernel_syms",                 /* 170 */
632+	"query_module",                    /* 171 */
633+	"quotactl",                        /* 172 */
634+	"nfsservctl",                      /* 173 */
635+	"getpmsg",                         /* 174 */
636+	"putpmsg",                         /* 175 */
637+	"afs_syscall",                     /* 176 */
638+	"reserved177",                     /* 177 */
639+	"gettid",                          /* 178 */
640+	"readahead",                       /* 179 */
641+	"setxattr",                        /* 180 */
642+	"lsetxattr",                       /* 181 */
643+	"fsetxattr",                       /* 182 */
644+	"getxattr",                        /* 183 */
645+	"lgetxattr",                       /* 184 */
646+	"fgetxattr",                       /* 185 */
647+	"listxattr",                       /* 186 */
648+	"llistxattr",                      /* 187 */
649+	"flistxattr",                      /* 188 */
650+	"removexattr",                     /* 189 */
651+	"lremovexattr",                    /* 190 */
652+	"fremovexattr",                    /* 191 */
653+	"tkill",                           /* 192 */
654+	"reserved193",                     /* 193 */
655+	"futex",                           /* 194 */
656+	"sched_setaffinity",               /* 195 */
657+	"sched_getaffinity",               /* 196 */
658+	"cacheflush",                      /* 197 */
659+	"cachectl",                        /* 198 */
660+	"sysmips",                         /* 199 */
661+	"io_setup",                        /* 200 */
662+	"io_destroy",                      /* 201 */
663+	"io_getevents",                    /* 202 */
664+	"io_submit",                       /* 203 */
665+	"io_cancel",                       /* 204 */
666+	"exit_group",                      /* 205 */
667+	"lookup_dcookie",                  /* 206 */
668+	"epoll_create",                    /* 207 */
669+	"epoll_ctl",                       /* 208 */
670+	"epoll_wait",                      /* 209 */
671+	"remap_file_pages",                /* 210 */
672+	"rt_sigreturn",                    /* 211 */
673+	"set_tid_address",                 /* 212 */
674+	"restart_syscall",                 /* 213 */
675+	"semtimedop",                      /* 214 */
676+	"fadvise64",                       /* 215 */
677+	"timer_create",                    /* 216 */
678+	"timer_settime",                   /* 217 */
679+	"timer_gettime",                   /* 218 */
680+	"timer_getoverrun",                /* 219 */
681+	"timer_delete",                    /* 220 */
682+	"clock_settime",                   /* 221 */
683+	"clock_gettime",                   /* 222 */
684+	"clock_getres",                    /* 223 */
685+	"clock_nanosleep",                 /* 224 */
686+	"tgkill",                          /* 225 */
687+	"utimes",                          /* 226 */
688+	"mbind",                           /* 227 */
689+	"get_mempolicy",                   /* 228 */
690+	"set_mempolicy",                   /* 229 */
691+	"mq_open",                         /* 230 */
692+	"mq_unlink",                       /* 231 */
693+	"mq_timedsend",                    /* 232 */
694+	"mq_timedreceive",                 /* 233 */
695+	"mq_notify",                       /* 234 */
696+	"mq_getsetattr",                   /* 235 */
697+	"vserver",                         /* 236 */
698+	"waitid",                          /* 237 */
699+	"238",                             /* 238 */
700+	"add_key",                         /* 239 */
701+	"request_key",                     /* 240 */
702+	"keyctl",                          /* 241 */
703+	"set_thread_area",                 /* 242 */
704+	"inotify_init",                    /* 243 */
705+	"inotify_add_watch",               /* 244 */
706+	"inotify_rm_watch",                /* 245 */
707+	"migrate_pages",                   /* 246 */
708+	"openat",                          /* 247 */
709+	"mkdirat",                         /* 248 */
710+	"mknodat",                         /* 249 */
711+	"fchownat",                        /* 250 */
712+	"futimesat",                       /* 251 */
713+	"newfstatat",                      /* 252 */
714+	"unlinkat",                        /* 253 */
715+	"renameat",                        /* 254 */
716+	"linkat",                          /* 255 */
717+	"symlinkat",                       /* 256 */
718+	"readlinkat",                      /* 257 */
719+	"fchmodat",                        /* 258 */
720+	"faccessat",                       /* 259 */
721+	"pselect6",                        /* 260 */
722+	"ppoll",                           /* 261 */
723+	"unshare",                         /* 262 */
724+	"splice",                          /* 263 */
725+	"sync_file_range",                 /* 264 */
726+	"tee",                             /* 265 */
727+	"vmsplice",                        /* 266 */
728+	"move_pages",                      /* 267 */
729+	"set_robust_list",                 /* 268 */
730+	"get_robust_list",                 /* 269 */
731+	"kexec_load",                      /* 270 */
732+	"getcpu",                          /* 271 */
733+	"epoll_pwait",                     /* 272 */
734+	"ioprio_set",                      /* 273 */
735+	"ioprio_get",                      /* 274 */
736+	"utimensat",                       /* 275 */
737+	"signalfd",                        /* 276 */
738+	"timerfd",                         /* 277 */
739+	"eventfd",                         /* 278 */
740+	"fallocate",                       /* 279 */
741+	"timerfd_create",                  /* 280 */
742+	"timerfd_gettime",                 /* 281 */
743+	"timerfd_settime",                 /* 282 */
744+	"signalfd4",                       /* 283 */
745+	"eventfd2",                        /* 284 */
746+	"epoll_create1",                   /* 285 */
747+	"dup3",                            /* 286 */
748+	"pipe2",                           /* 287 */
749+	"inotify_init1",                   /* 288 */
750+	"preadv",                          /* 289 */
751+	"pwritev",                         /* 290 */
752+	"rt_tgsigqueueinfo",               /* 291 */
753+	"perf_event_open",                 /* 292 */
754+	"accept4",                         /* 293 */
755+	"recvmmsg",                        /* 294 */
756+	"fanotify_init",                   /* 295 */
757+	"fanotify_mark",                   /* 296 */
758+	"prlimit64",                       /* 297 */
759+	"name_to_handle_at",               /* 298 */
760+	"open_by_handle_at",               /* 299 */
761+	"clock_adjtime",                   /* 300 */
762+	"syncfs",                          /* 301 */
763+	"sendmmsg",                        /* 302 */
764+	"setns",                           /* 303 */
765+	"process_vm_readv",                /* 304 */
766+	"process_vm_writev",               /* 305 */
767diff --git a/sysdeps/linux-gnu/mips/trace.c b/sysdeps/linux-gnu/mips/trace.c
768index e81b374..d54818e 100644
769--- a/sysdeps/linux-gnu/mips/trace.c
770+++ b/sysdeps/linux-gnu/mips/trace.c
771@@ -1,5 +1,6 @@
772 /*
773  * This file is part of ltrace.
774+ * Copyright (C) 2015 Imagination Technologies Limited
775  * Copyright (C) 2013 Petr Machata, Red Hat Inc.
776  * Copyright (C) 2012 Edgar E. Iglesias, Axis Communications
777  * Copyright (C) 2010 Arnaud Patard, Mandriva SA
778@@ -29,6 +30,7 @@
779 #include <signal.h>
780 #include <sys/ptrace.h>
781 #include <asm/ptrace.h>
782+#include <asm/unistd.h>
783 #include <assert.h>
784 #include <asm/unistd.h>
785
786@@ -68,6 +70,44 @@
787 void
788 get_arch_dep(struct process *proc)
789 {
790+#ifdef __LP64__
791+	proc->mask_32bit = (proc->e_class == ELFCLASS32);
792+#endif /* __LP64__ */
793+	/* n32 personality is best approximated by n64,
794+	   at least for syscall numbers */
795+	proc->personality = (proc->e_class == ELFCLASS64
796+			     || proc->e_abi == ABI_N32);
797+}
798+
799+/**
800+   \param abi ABI of current process, from mips_abi_type enum
801+   \param list An array of 4 elements, each corresponding to an ABI, in
802+   the order: o32, n32, n64, o64
803+
804+   return value from array corresponding to requested ABI
805+ */
806+static int
807+abi_select(const int abi, const int list[])
808+{
809+	int retval;
810+	switch (abi)
811+	{
812+	case ABI_N32:
813+		retval = list[1];
814+		break;
815+	case ABI_N64:
816+		retval = list[2];
817+		break;
818+	case ABI_O64:
819+		retval = list[3];
820+		break;
821+	case ABI_O32:
822+	default:
823+		retval = list[0];
824+		break;
825+	}
826+
827+	return retval;
828 }
829
830 /**
831@@ -90,53 +130,94 @@ get_arch_dep(struct process *proc)
832 int
833 syscall_p(struct process *proc, int status, int *sysnum)
834 {
835-	if (WIFSTOPPED(status)
836-			&& WSTOPSIG(status) == (SIGTRAP | proc->tracesysgood)) {
837-		/* get the user's pc (plus 8) */
838-		long pc = (long)get_instruction_pointer(proc);
839-		/* fetch the SWI instruction */
840-		int insn = ptrace(PTRACE_PEEKTEXT, proc->pid, pc - 4, 0);
841-		int num = ptrace(PTRACE_PEEKTEXT, proc->pid, pc - 8, 0);
842-
843-		/*
844-		   On a mips,  syscall looks like:
845-		   24040fa1    li v0, 0x0fa1   # 4001 --> _exit syscall
846-		   0000000c    syscall
847-		 */
848-		if(insn!=0x0000000c){
849-			/* sigreturn returns control to the point
850-			   where the signal was received; skip check
851-			   for preceeding syscall instruction */
852-			int depth = proc->callstack_depth;
853-			struct callstack_element *top = NULL;
854-			if (depth > 0)
855-				top = &proc->callstack[depth - 1];
856-
857-			if (top != NULL &&  top->is_syscall &&
858-			    (top->c_un.syscall == (__NR_rt_sigreturn -
859-						   __NR_Linux) ||
860-			     top->c_un.syscall == (__NR_sigreturn -
861-						   __NR_Linux))) {
862-				*sysnum = top->c_un.syscall;
863-				return 2;
864-			}
865-			else
866-				return 0;
867-		}
868-
869-		*sysnum = (num & 0xFFFF) - 4000;
870-		/* if it is a syscall, return 1 or 2 */
871-		if (proc->callstack_depth > 0 &&
872-				proc->callstack[proc->callstack_depth - 1].is_syscall &&
873-				proc->callstack[proc->callstack_depth - 1].c_un.syscall == *sysnum) {
874+	unsigned long pc;
875+	int insn, prev;
876+	int min_syscall, max_syscall, sigreturn, rt_sigreturn;
877+	struct callstack_element *top = NULL;
878+	int depth = proc->callstack_depth;
879+	const int syscallbase[] = {__NR_O32_Linux, __NR_N32_Linux,
880+				   __NR_64_Linux, __NR_O32_Linux};
881+	const int syscallnum[] = {__NR_O32_Linux_syscalls,
882+				  __NR_N32_Linux_syscalls,
883+				  __NR_64_Linux_syscalls,
884+				  __NR_O32_Linux_syscalls};
885+	const int rt_sigreturn_list[] = {193, 211, 211, 193};
886+	const int sigreturn_list[] = {119, -1, -1, 119};
887+
888+	if (!WIFSTOPPED(status)
889+	    || WSTOPSIG(status) != (SIGTRAP | proc->tracesysgood))
890+		return 0;
891+
892+	/* get the user's pc (plus 8) */
893+	pc = (unsigned long)get_instruction_pointer(proc);
894+	/* fetch the SWI instruction */
895+	insn = ptrace(PTRACE_PEEKTEXT, proc->pid, pc - 4, 0);
896+	prev = ptrace(PTRACE_PEEKTEXT, proc->pid, pc - 8, 0);
897+
898+	if (depth > 0)
899+		top = &proc->callstack[depth - 1];
900+
901+	/* Range of syscall numbers varies with ABI; ref:asm/unistd.h */
902+	min_syscall = abi_select(proc->e_abi, syscallbase);
903+	max_syscall = min_syscall + abi_select(proc->e_abi, syscallnum);
904+	sigreturn = min_syscall + abi_select(proc->e_abi, sigreturn_list);
905+	rt_sigreturn = min_syscall + abi_select(proc->e_abi, rt_sigreturn_list);
906+
907+	/* not a syscall instruction */
908+	if(insn!=0x0000000c){
909+		/* sigreturn returns control to the point where the signal was
910+		   received; skip check for preceeding syscall instruction */
911+		if (top != NULL &&  top->is_syscall
912+		    && (top->c_un.syscall == (rt_sigreturn - min_syscall)
913+			|| top->c_un.syscall == (sigreturn - min_syscall))) {
914+			*sysnum = top->c_un.syscall;
915 			return 2;
916 		}
917+		else
918+			return 0;
919+	}
920
921-		if (*sysnum >= 0) {
922-			return 1;
923-		}
924+	/*
925+	  On a mips,  syscall looks like:
926+	  24020fa1    li v0, 0x0fa1   # 4001 --> _exit syscall
927+	  0000000c    syscall
928+	*/
929+	if ((prev & 0xFFFF0000) == 0x24020000) {
930+		*sysnum = (prev & 0xFFFF) - min_syscall;
931 	}
932-	return 0;
933+	/*
934+	  The above is not necessary in Linux kernel > v2.6.35. Recent
935+	  kernels have a fancy-pants method of restarting syscalls.
936+	  We must read v0 instead, to get the syscall number.
937+
938+	  Unfortunately, v0 is not preserved till the point of return.
939+	  If already in syscall and v0 is invalid, assume this event
940+	  to be a return without attempting to match previous syscall.
941+
942+	  Caveat: logic fails if v0 incidentally contains a valid
943+	  syscall number, distinct from the current syscall number,
944+	  at the point of return from a nested syscall.
945+	*/
946+	else {
947+		int v0 = ptrace(PTRACE_PEEKUSER, proc->pid, off_v0, 0);
948+
949+		if ((v0 >= min_syscall) && (v0 <= max_syscall))
950+			*sysnum = v0 - min_syscall;
951+		else if (depth > 0 && top->is_syscall)
952+			*sysnum = top->c_un.syscall;
953+		else /* syscall instruction without valid number - ignored */
954+			return 0;
955+	}
956+
957+	/* if it is a syscall, return 1 or 2 */
958+	if (depth > 0 && top->is_syscall && top->c_un.syscall == *sysnum) {
959+		return 2;
960+	}
961+
962+	if (*sysnum >= 0)
963+		return 1;
964+	else
965+		return 0;
966 }
967
968 /* Based on GDB code.  */
969@@ -162,9 +243,11 @@ mips32_relative_offset (uint32_t inst)
970   return ((itype_immediate(inst) ^ 0x8000) - 0x8000) << 2;
971 }
972
973-int mips_next_pcs(struct process *proc, uint32_t pc, uint32_t *newpc)
974+int mips_next_pcs(struct process *proc, unsigned long pc,
975+		  unsigned long *newpc)
976 {
977-	uint32_t inst, rx;
978+	uint32_t inst;
979+	unsigned long rx;
980 	int op;
981 	int rn;
982 	int nr = 0;
983@@ -277,8 +360,8 @@ int mips_next_pcs(struct process *proc, uint32_t pc, uint32_t *newpc)
984 	return nr;
985
986 fail:
987-	printf("nr=%d pc=%x\n", nr, pc);
988-	printf("pc=%x %x\n", newpc[0], newpc[1]);
989+	printf("nr=%d pc=%lx\n", nr, pc);
990+	printf("pc=%lx %lx\n", newpc[0], newpc[1]);
991 	return 0;
992 }
993
994@@ -304,17 +387,27 @@ fail:
995  * branches within the LL-SC sequence.
996  */
997 #define inrange(x,lo,hi) ((x)<=(hi) && (x)>=(lo))
998+/* Instruction encodings for atomic operations */
999+#ifdef __mips64
1000+#define op_SC_p(op)	(op == 0x38 || op == 0x3c)
1001+#define op_LL_p(op)	(op == 0x30 || op == 0x34)
1002+#else /* !__mips64 */
1003+#define op_SC_p(op)	(op == 0x38)
1004+#define op_LL_p(op)	(op == 0x30)
1005+#endif /* !__mips64 */
1006+
1007 static int
1008-mips_atomic_next_pcs(struct process *proc, uint32_t lladdr, uint32_t *newpcs)
1009+mips_atomic_next_pcs(struct process *proc, unsigned long lladdr,
1010+		     unsigned long *newpcs)
1011 {
1012 	int nr = 0;
1013
1014-	uint32_t scaddr;
1015+	unsigned long scaddr;
1016 	for (scaddr = lladdr + 4; scaddr - lladdr <= 2048; scaddr += 4) {
1017 		/* Found SC, now stepover trailing branch */
1018 		uint32_t inst;
1019 		if (proc_read_32(proc, (arch_addr_t)scaddr, &inst) >= 0 &&
1020-		    itype_op(inst) == 0x38) {
1021+		    op_SC_p (itype_op(inst))) {
1022 			newpcs[nr++] = scaddr + 4;
1023 			break;
1024 		}
1025@@ -327,16 +420,16 @@ mips_atomic_next_pcs(struct process *proc, uint32_t lladdr, uint32_t *newpcs)
1026 	}
1027
1028 	/* Scan LL<->SC range for branches going outside that range */
1029-	uint32_t spc;
1030+	unsigned long spc;
1031 	for (spc = lladdr + 4; spc < scaddr; spc += 4) {
1032-		uint32_t scanpcs[2];
1033+		unsigned long scanpcs[2];
1034 		int snr = mips_next_pcs(proc, spc, scanpcs);
1035
1036 		int i;
1037 		for (i = 0; i < snr; ++i) {
1038 			if (!inrange(scanpcs[i], lladdr, scaddr)) {
1039-				uint32_t *tmp = realloc(newpcs, (nr + 1) *
1040-							sizeof *newpcs);
1041+				unsigned long *tmp = realloc(newpcs, (nr + 1)
1042+							     * sizeof *newpcs);
1043 				if (tmp == NULL) {
1044 					perror("malloc atomic next pcs");
1045 					return -1;
1046@@ -357,8 +450,8 @@ arch_sw_singlestep(struct process *proc, struct breakpoint *bp,
1047 		   int (*add_cb)(arch_addr_t, struct sw_singlestep_data *),
1048 		   struct sw_singlestep_data *add_cb_data)
1049 {
1050-	uint32_t pc = (uint32_t) get_instruction_pointer(proc);
1051-	uint32_t *newpcs;
1052+	unsigned long pc = (unsigned long) get_instruction_pointer(proc);
1053+	unsigned long *newpcs;
1054 	int nr;
1055 	uint32_t inst;
1056
1057@@ -369,7 +462,7 @@ arch_sw_singlestep(struct process *proc, struct breakpoint *bp,
1058 		return SWS_FAIL;
1059
1060 	/* Starting an atomic read-modify-write sequence */
1061-	if (itype_op(inst) == 0x30)
1062+	if (op_LL_p(itype_op(inst)))
1063 		nr = mips_atomic_next_pcs(proc, pc, newpcs);
1064 	else
1065 		nr = mips_next_pcs(proc, pc, newpcs);
1066@@ -462,7 +555,7 @@ gimme_arg(enum tof type, struct process *proc, int arg_num,
1067 				debug(2,"ret = %#lx",addr);
1068 				return addr;
1069 			}
1070-			ret = addr + 4*arg_num;
1071+			ret = addr + sizeof(long) * arg_num;
1072 			ret=ptrace(PTRACE_PEEKTEXT,proc->pid,addr,0);
1073 			debug(2,"ret = %#lx",ret);
1074 			return ret;
1075@@ -474,7 +567,7 @@ gimme_arg(enum tof type, struct process *proc, int arg_num,
1076 			debug(2,"ret = %#lx",addr);
1077 			return addr;
1078 		}
1079-		ret = addr + 4*arg_num;
1080+		ret = addr + sizeof(long) * arg_num;
1081 		ret=ptrace(PTRACE_PEEKTEXT,proc->pid,addr,0);
1082 		debug(2,"ret = %#lx",ret);
1083 		return ret;
1084@@ -483,4 +576,34 @@ gimme_arg(enum tof type, struct process *proc, int arg_num,
1085 	return 0;
1086 }
1087
1088+#ifdef __LP64__
1089+size_t
1090+arch_type_sizeof(struct process *proc, struct arg_type_info *info)
1091+{
1092+	if (proc == NULL)
1093+		return (size_t)-2;
1094+
1095+	switch (info->type) {
1096+	case ARGTYPE_LONG:
1097+	case ARGTYPE_ULONG:
1098+		return proc->mask_32bit ? 4 : sizeof (long);
1099+
1100+	case ARGTYPE_POINTER:
1101+		return proc->mask_32bit ? 4 : sizeof (void *);
1102+
1103+	default:
1104+		/* Use default value.  */
1105+		return (size_t)-2;
1106+	}
1107+}
1108+
1109+size_t
1110+arch_type_alignof(struct process *proc, struct arg_type_info *info)
1111+{
1112+	if (proc == NULL)
1113+		return (size_t)-2;
1114+
1115+	return arch_type_sizeof(proc, info);
1116+}
1117+#endif /* __LP64__ */
1118 /**@}*/
1119diff --git a/sysdeps/linux-gnu/mksyscallent_mips b/sysdeps/linux-gnu/mksyscallent_mips
1120index f3961b4..f8dcfe1 100755
1121--- a/sysdeps/linux-gnu/mksyscallent_mips
1122+++ b/sysdeps/linux-gnu/mksyscallent_mips
1123@@ -19,9 +19,7 @@
1124
1125 # hack expression to generate arch/syscallent.h from <asm/unistd.h>
1126 # It reads from stdin and writes to stdout
1127-# It should work OK on i386,m68k,arm,ia64
1128-# It does NOT work in mips, s390
1129-# It is untested in other architectures
1130+# Default is o32; arch=mips64 generates n64 syscalls
1131
1132 BEGIN {
1133 	max=0;
1134@@ -31,7 +29,10 @@ BEGIN {
1135 {
1136 	#debug
1137 	#printf("/%s/%s/%s/%s/\n", $1, $2, $3, $4);
1138-	if ($2 ~ /__NR_Linux/ && $3 ~ /4000/) {
1139+        min=4000
1140+        if (arch ~ "mips64") min=5000
1141+
1142+	if ($2 ~ /__NR_Linux/ && $3 ~ min) {
1143 		syscall=1;
1144 	}
1145 	if ($2 ~ /__NR_Linux_syscalls/) {
1146--
11472.13.2
1148
1149