diff options
| -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 0000000000..d0daf1466f --- /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 213436c769..b613bc3af8 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 | ||
