diff options
author | Khem Raj <raj.khem@gmail.com> | 2017-07-01 12:54:55 -0700 |
---|---|---|
committer | Martin Jansa <Martin.Jansa@gmail.com> | 2017-07-14 23:44:30 +0200 |
commit | 27a7e20e2bb8722aad9dc59509fc0884f1b276b4 (patch) | |
tree | 9ce7e576db80ae4508c93300ce457de5b489bada /meta-oe/recipes-devtools | |
parent | f52cbdcbe5ca0a2c0b4f02a79dd46394817ead78 (diff) | |
download | meta-openembedded-27a7e20e2bb8722aad9dc59509fc0884f1b276b4.tar.gz |
ltrace: Add mips64 support
Signed-off-by: Khem Raj <raj.khem@gmail.com>
Signed-off-by: Martin Jansa <Martin.Jansa@gmail.com>
Diffstat (limited to 'meta-oe/recipes-devtools')
-rw-r--r-- | meta-oe/recipes-devtools/ltrace/ltrace/0001-Add-support-for-mips64-n32-n64.patch | 1148 | ||||
-rw-r--r-- | meta-oe/recipes-devtools/ltrace/ltrace_git.bb | 1 |
2 files changed, 1149 insertions, 0 deletions
diff --git a/meta-oe/recipes-devtools/ltrace/ltrace/0001-Add-support-for-mips64-n32-n64.patch b/meta-oe/recipes-devtools/ltrace/ltrace/0001-Add-support-for-mips64-n32-n64.patch new file mode 100644 index 000000000..d0daf1466 --- /dev/null +++ b/meta-oe/recipes-devtools/ltrace/ltrace/0001-Add-support-for-mips64-n32-n64.patch | |||
@@ -0,0 +1,1148 @@ | |||
1 | From 5f6dfafb80bdc2566fe91d5fde96769175fabf35 Mon Sep 17 00:00:00 2001 | ||
2 | From: Faraz Shahbazker <faraz.shahbazker@imgtec.com> | ||
3 | Date: Sat, 1 Jul 2017 10:56:59 -0700 | ||
4 | Subject: [PATCH] Add support for mips64 n32/n64 | ||
5 | |||
6 | Signed-off-by: Khem Raj <raj.khem@gmail.com> | ||
7 | --- | ||
8 | Upstream-Status: Pending | ||
9 | Source: 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 | |||
27 | diff --git a/backend.h b/backend.h | ||
28 | index 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, | ||
46 | diff --git a/ltrace-elf.c b/ltrace-elf.c | ||
47 | index 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 | ||
76 | diff --git a/proc.h b/proc.h | ||
77 | index 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. */ | ||
88 | diff --git a/sysdeps/linux-gnu/mips/Makefile.am b/sysdeps/linux-gnu/mips/Makefile.am | ||
89 | index 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 | ||
100 | diff --git a/sysdeps/linux-gnu/mips/abi.c b/sysdeps/linux-gnu/mips/abi.c | ||
101 | new file mode 100644 | ||
102 | index 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 | +/**@}*/ | ||
170 | diff --git a/sysdeps/linux-gnu/mips/arch.h b/sysdeps/linux-gnu/mips/arch.h | ||
171 | index 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 { | ||
227 | diff --git a/sysdeps/linux-gnu/mips/plt.c b/sysdeps/linux-gnu/mips/plt.c | ||
228 | index 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(<e->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 | |||
375 | diff --git a/sysdeps/linux-gnu/mips/signalent1.h b/sysdeps/linux-gnu/mips/signalent1.h | ||
376 | new file mode 100644 | ||
377 | index 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 */ | ||
433 | diff --git a/sysdeps/linux-gnu/mips/syscallent1.h b/sysdeps/linux-gnu/mips/syscallent1.h | ||
434 | new file mode 100644 | ||
435 | index 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 */ | ||
767 | diff --git a/sysdeps/linux-gnu/mips/trace.c b/sysdeps/linux-gnu/mips/trace.c | ||
768 | index 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 | /**@}*/ | ||
1119 | diff --git a/sysdeps/linux-gnu/mksyscallent_mips b/sysdeps/linux-gnu/mksyscallent_mips | ||
1120 | index 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 | -- | ||
1147 | 2.13.2 | ||
1148 | |||
diff --git a/meta-oe/recipes-devtools/ltrace/ltrace_git.bb b/meta-oe/recipes-devtools/ltrace/ltrace_git.bb index 213436c76..b613bc3af 100644 --- a/meta-oe/recipes-devtools/ltrace/ltrace_git.bb +++ b/meta-oe/recipes-devtools/ltrace/ltrace_git.bb | |||
@@ -22,6 +22,7 @@ SRC_URI = "git://anonscm.debian.org/collab-maint/ltrace.git;branch=master \ | |||
22 | file://0002-Fix-const-qualifier-error.patch \ | 22 | file://0002-Fix-const-qualifier-error.patch \ |
23 | file://0001-ARM-code-has-unreachable-code-after-switch-statement.patch \ | 23 | file://0001-ARM-code-has-unreachable-code-after-switch-statement.patch \ |
24 | file://0001-Fix-tautological-compare-warning.patch \ | 24 | file://0001-Fix-tautological-compare-warning.patch \ |
25 | file://0001-Add-support-for-mips64-n32-n64.patch \ | ||
25 | " | 26 | " |
26 | S = "${WORKDIR}/git" | 27 | S = "${WORKDIR}/git" |
27 | 28 | ||